目录
一、线程
1、线程理论
进程与线程的区别:
-
进程:
- 进程是资源单位,表示一块内存空间
-
线程:
- 线程是执行单位,指在进程内的代码指令
? 可以将进程比喻成车间,线程就是车间里的流水线
? 一个进程内至少含有一个线程
线程的特点:
? 1、一个进程内可以开设多条线程
? 2、同一个进程下的线程之间数据是共享的
? 3、创建线程的消耗要小于进程(创建时间小于创建进程时间)
2、创建线程的两种方式
2、1.继承类创建
创建顺序:
? 1、导入 threading import Thread 模块
? 2、生成一个类
? 3、使用类继承 Thread
? 4、生成类体代码
? 5、使用类生成对象,并调用
? 6、每次调用的对象就是不同的线程
代码用法:
from threading import Thread
class MyThread(Thread):
def run(self):
print('run is running')
time.sleep(1)
print('run is over')
obj = MyThread()
obj.start()
print('主线程')
2、2.使用函数创建
创建顺序:
? 1、导入 threading import Thread 模块
? 2、生成函数(功能代码)
? 3、定义线程对象,并在参数内填入需要加载的子线程函数
? 4、使用进程对象加‘点’start()的方式启动子线程
代码用法:
from threading import Thread
import time
def task(name):
print(f'{name} is running')
time.sleep(0.1)
print(f'{name} is over')
if __name__ == '__main__':
for i in range(100):
t = Thread(target=task, args=('用户%s'%i,))
t.start()
3、线程的诸多特性
1、join()
使异步变为同步,使子线程代码执行结束向下执行主线程代码
2、多个线程之间数据共享
3、current_thread()
查看线程名字
4、active_count()
查看当前进程下线程的数量
二、GIL全局解释器锁
1、简介
官方简介:
In CPython, the global interpreter lock, or GIL, is a mutex that prevents multiple native threads from executing Python bytecodes at once. This lock is necessary mainly because CPython’s memory management is not thread-safe. (However, since the GIL exists, other features have grown to depend on the guarantees that it enforces.
'''
在CPython中,全局解释器锁(GIL)是一个互斥锁,它可以防止多个本地线程同时执行Python字节码。这个锁是必要的,主要是因为CPython的内存管理不是线程安全的。(然而,自从GIL存在以来,其他特性已经依赖于它强制执行的保证。
'''
简译:
1、在cpython解释器中,存在全局解释器锁,简称GIL
python解释器的类型有很多
cpython>>>:基于C开发的python (常用)
jpython>>>:基于Java开发的python
pypython>>>:基于py开发的python
2、GIL本质也是一把互斥锁,用来阻止同一个进程内多个线程的安全
同一个进程下的多个线程,如果在没有互斥锁的情况下,同样会产生对数据的处理不准确的情况
3、GIL的存在是因为CPython解释器中内存管理不是线程安全的
垃圾回收机制的本质也是一种线程,如果线程的本质不是串行的话,那么在我们每将定义一个变量时,就会被垃圾机制立马检测,将定义的数据清空
2、验证GIL的存在
推导流程:
? 1、导入线程模块
? 2、定义一个全局变量
? 3、定义一个函数体代码
? 4、生成多个线程模块
? 5、创建的多个线程修改全局变量
? 6、得到的结果是多个线程依次修改的
结论:
? 线程的执行是同步的,如果是异步的话那么修改的全局变量就会产生混乱
代码表现:
from threading import Thread
num = 100
def task():
global num
num -= 1
t_list = []
for i in range(100):
t = Thread(target=task)
t.start()
t_list.append(t)
for t in t_list:
t.join()
print(num)
3、GIL与普通互斥锁
? 虽然cpython的线程中自带GIL,但在创建多个线程时,任需要考虑到多种情况
- GIL只能确保同进程内的多个线程数据不被垃圾回收机制弄乱
- GIL并不能保证序列里数据的安全
- 在使用线程处理数据时,任需要针对各种情况加‘锁’
代码表现:
def task(mutex):
global num
mutex.acquire()
count = num
time.sleep(0.1)
num = count - 1
mutex.release()
mutex = Lock()
t_list = []
for i in range(100):
t = Thread(target=task,args=(mutex,))
t.start()
t_list.append(t)
for t in t_list:
t.join()
print(num)
4、python多线程是否有用
? 因为cpython的线程自带GIL机制,那么处理数据起来就相对较慢,那么cpython的线程是否就很鸡肋呢,需要分以下情况
情况一:
单个cpu
多个cpu
情况二:
IO密集型(代码有IO操作)
计算密集型(代码没有IO操作)
1、单个cup + IO密集型
多进程打开内存空间较慢,而打开线程时间较短,所以这种情况线程有较大优势
# 多线程具有优势
2、单个CPU + 计算密集型
多进程打开内存空间较慢,而打开线程时间较短,所以这种情况线程有较大优势
# 多线程具有优势
3、多个CPU + IO密集型
多进程打开内存空间较慢,而打开线程时间较短,所以这种情况线程有较大优势
# 多线程具有优势
4、多个CPU + 计算密集型
多个CPU下进程计算的时间时多个进程的综合,而线程是多个子线