目录
- GIL是什么
- GIL产生的原因
- 如何避免受到GIL的影响
- 什么时候会释放GIL锁
- 互斥锁和Gil锁的关系
参考链接
python中的GIL详解
python面试不得不知道的点——GIL
《Python面试每日一题》之GIL
Python GIL 是功能和性能之间权衡后的产物,它尤其存在的合理性,也有较难改变的客观因素
GIL是什么
- 全局解释器锁(global interpreter lock),每个线程在执行时候都需要 先获取GIL,保证同一时刻只有一个线程可以执行代码,即同一时刻只有一个线程使用CPU,也就是说 多线程并不是真正意义上的同时执行
‘
GIL产生的原因
- 创建python时就 只考虑到单核CPU,解决多线程之间数据完整性和状态同步的最简单方法自然就是加锁, 于是有了GIL这把超级大锁
- Cpython(使用C语言编写的Python解释器)的 内存管理不是线程安全 的
- 因为cpython解析只允许拥有GIL全局解析器锁才能运行程序,这样就保证了保证同一个时刻只允许一个线程可以使用 CPU
- 当使用Cpython解释器解释多线程程序时,为了保证线程安全,即共享资源的原子性。默认使用了一个GIL,导致多线程实际是 “伪多线程”
如何避免受到GIL的影响
用multiprocess替代Thread
- multiprocess库的出现很大程度上是为了弥补thread库因为GIL而低效的缺陷
- 它完整的复制了一套thread所提供的接口方便迁移
- 唯一的不同就是它使用了 多进程 而不是多线程。每个进程有自己的独立的GIL,因此也不会出现进程之间的GIL争抢
- 但其引入会 增加程序实现时线程间数据通讯和同步的困难
- 就拿计数器来举例子,如果我们要多个线程累加同一个变量,对于thread来说,申明一个global变量,用thread.Lock的context包裹住三行就搞定了。而multiprocess由于进程之间无法看到对方的数据,只能通过在主线程申明一个Queue,put再get或者用share memory的方法。这个额外的实现成本使得本来就非常痛苦的多线程程序编码,变得更加痛苦了
用其他解析器
【不推荐】
- GIL只是CPython的产物,但像 JPython和IronPython 这样的解析器由于实现语言的特性,他们不需要GIL的帮助
- 然而由于用了Java/C#用于解析器实现,他们也失去了利用社区众多C语言模块有用特性的机会,所以这些解析器也因此一直都比较小众
- 毕竟功能和性能大家在初期都会选择前者,Done is better than perfect
在使用多线程可以使用c语言去实现
什么时候会释放GIL锁
- 遇到像 I/O 操作这种 会有时间空闲情况 造成 CPU 闲置 的情况会释放GIL
- 会有一个专门ticks进行计数 一旦 ticks数值达到100 这个时候释放GIL锁 线程之间开始竞争Gil锁
- 说明: ticks这个数值可以进行设置来延长或者缩减获得GIL锁的线程使用cpu的时间
互斥锁和Gil锁的关系
- Gil锁 : 保证同一时刻只有一个线程能使用到cpu
- 互斥锁 : 多线程时,保证修改共享数据时有序的修改,不会产生数据修改混乱