讲GIL之前先弄清楚几个小概念
1. 同步IO&异步IO
同步IO:当程序执行到IO操作时,等数据来了才进行下一步操作,数据不来就阻塞在IO操作处。
异步IO:当程序执行到IO操作时,不等,就去执行其他代码了。一段时间后,当IO返回结果时,再通知CPU进行处理。
如何实现异步IO也是一个问题,到时候另讲。
2. 并行&并发
并行:系统具有同时处理多任务的能力,由多CPU同时运行实现。
并发:系统具有处理多任务的能力,单核CPU就能实现,由CPU分时轮循任务实现。
3. 多任务分类
IO密集型与计算密集型
GIL(全局解释锁)----CPython解释器才有:
对一个进程,无论你启动多少个线程,你有多少个cpu,python在执行的时候会淡定的在同一时刻只允许一个线程运行。
问题1:CPython解释器为何要对进程加GIL锁?
因为GIL能很好的保护线程安全,而龟叔认为保证线程安全比实现并行更重要。
问题2:那python对于处理多任务的情况怎么办?
对于IO密集型多任务,CPython会在IO阻塞时将线程转为阻塞状态,换其他就绪状态线程执行。这样对于IO密集型多任务用多线程就可以大大提高CPU利用率(任然时单核)。
对于计算密集型多任务,有多种替代方案可选①:多进程+协程;②:用python提供的扩展接口将计算密集型多任务程序由C语言实现,即让C来实现真正的并发操作,而将计算结果返回给python接口。光靠Python是无法从根本上实现计算密集型多任务的并行。
问题3:什么时候释放GIL锁?
①:1 遇到像 i/o操作这种 会有时间空闲情况 造成cpu闲置的情况会释放Gil
②:会有一个专门ticks进行计数 一旦ticks数值达到100 这个时候释放Gil锁 线程之间开始竞争Gil锁(说明:ticks这个数值可以进行设置来延长或者缩减获得Gil锁的线程使用cpu的时间)
问题4: 互斥锁和GIL锁的关系
GIL锁 : 保证同一时刻只有一个线程能使用到cup
互斥锁 : 多线程时,保证修改共享数据时有序的修改,不会产生数据修改混乱
执行以下步骤
(1)多线程运行,假设Thread1获得GIL可以使用cpu,这时Thread1获得 互斥锁lock,Thread1可以改date数据(但并
没有开始修改数据)
(2)Thread1线程在修改date数据前发生了 i/o操作 或者 ticks计数满100 (注意就是没有运行到修改data数据),这个
时候 Thread1 让出了Gil,Gil锁可以被竞争
(3) Thread1 和 Thread2 开始竞争 Gil (注意:如果Thread1是因为 i/o 阻塞 让出的Gil Thread2必定拿到Gil,如果
Thread1是因为ticks计数满100让出Gil 这个时候 Thread1 和 Thread2 公平竞争)
(4)假设 Thread2正好获得了GIL, 运行代码去修改共享数据date,由于Thread1有互斥锁lock,所以Thread2无法更改共享数据
date,这时Thread2让出Gil锁 , GIL锁再次发生竞争