一、GIL是什么,它为什么会存在
python被人诟病最多的大概就是它的GIL全局锁了,但我今天要为它正名,这与python本身没有关系,而是与它的解释器有关系。
我们知道,python代码编写好,最终运行的是一个.py的文件,运行代码的过程,其实就是让解释器把我们编写的代码解释给机器能识别的语言的过程。可以解释python代码的解释器有很多,如:
- cpython(官方解释器)
- ipython(基于cpython的一种解释器,交互更强,其他与cpython一样)
- pypy(采用JIT(Just In Time)也就是即时编译编译器,对Python代码执行动态编译,目的是加快执行速度)
- jython(Java平台上的解释器)
- ironpython(与jython类似,只不过ironPython是运行在微软.Net平台上的Python解释器)
官方使用的解释器是cpython,也就是当我们从官网下载安装python的时候,就已经默认使用python解释器是cpython。而GIL就是cpython在解释python代码的时候给它加的一个锁,GIL全称是Global Interpreter Lock(全局解释器锁),所以GIL与cpython有关,与python无关,你可以换一种没有GIL的解释器。
那么GIL为什么会存在呢,官网的解释是:GIL是一个互斥锁,它防止多个线程同时执行Python字节码,这个锁是必要的,主要是因为CPython的内存管理不是线程安全的。有点晕。再理解一下,Python内部对变量或数据对象使用了引用计数器,我们通过计算引用个数,当个数为0时,变量或者数据对象就被自动释放。而引用个数需要被保护起来,多个线程可能会同时去修改它,那么可能引起内存泄露,那我们就引入锁吧,多个锁可能导致死锁问题,所以为了一劳永逸,荷兰人python之父Guido van Rossum(吉多·范罗苏姆)在默认的解释器CPython使用了单锁,即全局解释器锁GIL。在执行Python字节码时都需要获取GIL,这可以防止死锁,但却也带来一个问题,它有效地使任何受CPU限制的Python程序都是单线程。
二、GIL对编码有什么影响
GIL它有效地使任何受CPU限制的Python程序都是单线程。所以主要影响的是多线程的运行效率,但也不是一定会影响。这是什么意思呢?
我们在工作中难免会遇到多任务的场景,我们的解决办法无非就是那几种,多线程、多进程、协程,或者它们的组合来并行或者并发的执行任务,我们这篇文章里只谈论假如你采用的方法是多线程的时候,因为GIL只会影响多线程。所有的多任务场景,它们是可以被区分为计算密集型(CPU)和I/O密集型的,如果你的多任务是I/O密集型,那么恭喜你,多线程你想用就用,GIL对它没有多大影响,而如果你的多任务是计算密集型,那么很不幸,你最好别使用多线程的方式来解决,因为不起作用,甚至还会因为锁的获取和释放增加开销。
我们列举一下计算密集型和I/O密集型大概都包含哪些任务:
- 计算密集型:简单说就是计算量大,对CPU要求比较高,数学计算、矩阵运算、搜索、图像处理等等
- I/O密集型:Input Ouput,输入输出嘛,数据来回传输,文件操作、数据库、网络I/O等等
可以根据自己的具体业务场景选择,来决定是否适合多线程编码。
三、什么时候GIL会交出cpu使用权
- I/O密集型操作,在等待时候,cpu空闲时会交出GIL锁
- python里有一个专门ticks进行计数,ticks数值达到100的时候就会释放Gil锁(说明:ticks这个数值可以进行设置来延长或者缩减获得Gil锁的线程使用cpu的时间)
四、总结
- GIL是cpython这个解释器带来的一种针对内存泄露和死锁问题的解决方案,并不是python自带的。
- 对于多任务问题,如果是I/O密集型,多线程使用没问题,如果是计算密集型,谨慎。
来源:https://www.cnblogs.com/wsjgdxx/p/12044168.html