一、GIL
1、什么是GIL
GIL:global interpreter lock 全局解释器锁,只存在于CPython中
保证了同一时候只有一个线程在执行
2、有了GIL会对单进程下的多个线程造成什么样的影响
单进程下的多个线程只能串行执行
3、为什么要有GIL
为了防止多个线程同时竞争python解释器资源
4、GIL与自定义互斥锁的区别,多个线程争抢GIL与自定义互斥锁的过程分析
在Python多线程下,每个线程的执行方式:
1、获取GIL
2、执行代码直到sleep或者是i操作或者是代码执行结束
3、释放GIL
子线程在拿到cpu执行权时,自动获得一个GIL全局解释器锁,当遇到sleep或者io或者线程执行完毕时会自动解锁这个时候需要自定义一把锁,保证线程安全,数据不错乱
5、什么时候用python的多线程,什么时候用多进程,为什么?
IO密集型代码使用多线程
CPU密集型代码(各种循环处理、计数等等)使用多进程
二、进程池与线程池
1、池的用途,为何要用它
池是一个容器,为来方便管理进程或者线程
2、池子里什么时候装进程什么时候装线程?
很多时候进程是空闲的 就让他进入进程池 让有任务处理时才从进程池取出来使用
ProcessPoolExecutor类
创建时指定最大进程数 自动创建进程
调用submit函数将任务提交到进程池中
创建进程是在调用submit后发生的
总结一下:
进程池可以自动创建进程
进程限制最大进程数
自动选择一个空闲的进程帮你处理任务
进程什么时候算是空闲?
代码执行完算是空闲
GIL详解
import time
from threading import Thread,current_thread,Lock
x=1
def task1():
time.sleep(2)
global x
x=2
print(current_thread(),x)
def task2():
time.sleep(10)
global x
x=3
print(current_thread(),x)
t1=Thread(target=task1)
t2=Thread(target=task2)
t1.start()
t2.start()
print('这是主线程的',x)
'''
刚开始时,只有主线程在使用CPU的执行权,因为其他两个线程还没有被创建,这时主线程的代码就自上而下的去执行
本应该输出x=1 但是由于cpu计算太快,导致t1.start和t2.start,才执行到主线程的print代码,结果输出为3
为了还原真实的执行顺序,在每个task里面加time.sleep(2)
当主线程的内容执行完毕后,就开始创建并启动其他的线程,每个线程将主线程的代码复制了一份,
此时,栈中有三个线程:主线程、Thread-2和Thread-1线程。但是主线程已经没有了要执行的代码,所以现在相当于只有Thread-2和Thread-1线程在执行,
因此我们会看到这两个线程在轮流抢占CPU的执行权来输出他们各自的内容。此时的结果输出为1
子线程在拿到cpu执行权时,自动获得一个GIL全局解释器锁,当遇到sleep或者io或者线程执行完毕时会自动解锁
这个时候需要自定义一把锁,保证线程安全,数据不错乱
'''