Fuhui

Python中的进程线程协程


进程

线程

协程

是一种用户级的轻量级的线程,拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器和栈存放在指定地方,在切换回来的时候,恢复先前的上下文和栈

GIL

GIL,即Global Interpreter Lock全局解释器锁,保证任何时刻仅有一个线程在执行。常见例子有CPython(JPython不使用GIL)与Ruby MRI。 不是所有的Python解释器都有GIL。

为什么要有GIL这个东西,不能去掉呢?这是为了实现GC,避免Java里Full GC(stop the world)引入的。更多内容参考 python 线程,GIL 和 ctypes

每个进程一把锁🔒,进程里的线程,只能有一个线程可以获得这把锁,进行工作,其他线程必须等待

在Python语言的主流实现CPython中,GIL 是一个货真价实的全局线程锁,在解释器解释执行任何Python代码时,都需要先获得这把锁才行, 在遇到I/O操作时会释放这把锁。如果是纯计算的程序,没有I/O操作,解释器会每隔100次操作就释放这把锁,让别的线程有机会执行(这个次数可以通过 sys.setcheckinterval 来调整)

同一进程下的多线程共享数据,共享意味着竞争,竞争带来无序,为了数据安全所以需要加锁进行数据保护,GIL本质是一把互斥锁,使并发变为串行, 保证同一时间只有一条线程访问解释器级别的数据,这样就保证了解释器级别的数据安全,同时也带来了一些问题,同一进程只有一条线程执行任务, 无法利用多核优势,解决方案可以根据任务的类型来处理,如果是I/O密集型,则需要开多线程提高效率,如果是计算密集型则需要多进程。

遇到阻塞,普通单线程的做法是就地等待,多线程的做法是转去执行其他线程–这就是开多线程效率提高的原因。 但如果这种阻塞和放开是我们人为可以预料到的,那么我们可以在阻塞的地方yield返回到另一个可以执行的点,这样也实现了CPU的不浪费,同时还少了线程的切换,效率更高

python锁

python线程