当前位置: 首页 > 科技观察

Python是否可以删除GIL?

时间:2023-03-13 12:36:29 科技观察

我们知道在CPython中,有一个全局解释器锁,英文叫做globalinterpreterlock,简称GIL。它是一种互斥锁,用于保护Python世界中的对象,防止多个线程同时执行Python。字节码保证线程安全,这使得Python线程无法发挥多核CPU的优势,所以有人说Python的多线程是伪多线程,性能不高,那么Python有没有可能去掉GIL中的未来?要回答这个问题,首先分析一下GIL的由来。GIL的起源Python于1991年首次发布,当时的CPU都是单核的。在单核中,多线程主要是为了同时做IO和CPU计算而设计的。Python编译器是用C语言编写的,因此也被称为CPython。当时很多编程语言都没有自动内存管理的功能。Python为了实现自动垃圾回收,对每个对象进行了引用计数。当引用计数为0时,表示该对象可以被回收,从而释放内存。例如:>>>importsys>>>data={'gzh':'Python7号'}>>>var1=data>>>sys.getrefcount(data)3>>>这里有3个数据对象参考,一个是它本身,一个是变量var1,一个是getrefcount函数的参数。如果此时另一个线程引用了数据,那么引用计数就会加1。如果一个线程使用数据,操作结束,那么引用计数就减1,而如果多个线程修改同一个变量“引用计数”,他们会遇到竞争条件(竞争)。为了避免竞争条件,最简单有效的方法是添加一个互斥量。如果每个对象都加锁,可能会导致另一个问题,就是死锁,频繁的获取和释放会导致性能下降。最简单有效的方法就是加解释器锁,线程在执行任何字节码时总是先获取解释器锁,这样可以避免死锁,也不会消耗太多的性能。当时的CPU都是单核的,这个GIL的设计简单,不会影响性能,所以一直沿用到今天。GIL存在的主要原因是Python的内存管理不是线程安全的,这是GIL产生和存在的主要原因。尝试淘汰GIL进入CPU的多核时代后,可以同时做多个计算任务,GIL真的成了问题。1999年有个叫GregStein的家伙在Python1.5版本的基础上去掉了GIL,取而代之的是对变量数据结构加了更细粒度的锁,还提交了一个patch去掉了全局变量Object的依赖,然后就标准了测试表明,去除GIL后单线程比不去除时慢了近2倍,而且被测机器仍然是当时性能最好的Windows机器。也就是说去掉GIL后,可以使用2个CPU获得比原来1个CPU稍微好一些的性能。这种改进显然得不偿失,GregStein的尝试以失败告终。Python之父GuidovanRossum也欢迎社区志愿者尝试移除GIL,只要不降低单线程性能即可,但他也提到移除GIL并不是一件容易的事。Python开发人员邮件列表上偶尔会讨论关于GIL移除的问题,但必须满足以下要求:简单。从长远来看,解决方案必须是可实施和可维护的。同时。删除GIL必须提高多线程性能。速度。删除GIL不会降低单线程性能。满足CPython的特性。该方案必须支持CPython功能,例如__del__和弱引用。API兼容性。该方案应该与所有现有CPython扩展使用的宏源代码兼容。及时销毁不可达对象,回收内存。有序销毁,例如,如果一个不可达的对象X引用A,那么应该在销毁A之前销毁X(某些垃圾收集算法无法做到这一点)。有些要求不太容易满足,比如4、5、7。目前还没有人在满足上述要求的同时成功去除GIL。很难回来。Python这些年太火了。很多优秀的库都是基于CPython编写的,其中有不少是90年代的C扩展库。如果要去掉GIL,很多基于GIL写的C扩展就不能用了,也就是说,没有GIL,Python生态中有很多扩展或者第三方库就不能用了。另一个明显的例子是,不仅有针对Python的CPython解释器,还有用Java编写的Python和.NET实现的IronPython。这些解释器根本没有GIL,但是有多少人为它们编写扩展?Python之所以如此受欢迎,与其拥有丰富的开箱即用的三方库有很大关系。很难找回来,也很难去除GIL。为什么Python3一开始没有去掉GIL不被社区接受的原因。与Python2相比,删除GIL会让Python3在单线程性能上变慢,很多优秀的扩展将不再可用。如果真是这样,可想而知Python3是不可能有未来的。最后的结果是Python3仍然保留了GIL。不过,Python3也为现有的GIL带来了重大改进。在Python3.2中,保证了计算密集型线程和I/O密集型线程共存时,I/O密集型任务长时间无法获取GIL而无法执行的问题,提升了多线程性能。最后,Python因为内存管理的关系不是线程安全的,所以它从一出生就有自己的GIL,很多扩展都是在GIL的保护下写的。线程性能下降和保留GIL的问题现在是Python3.9版本。Python以后去掉GIL的可能性很小。也就是说,去掉了GIL的Python并不是我们所知道的Python。不过不要灰心,GIL只影响计算密集型任务的多线程执行,大多数程序员很少遇到,即使有,也可以使用多进程来避免GIL的影响,或者使用其他编程方式语言实现,没有任何编程语言或技术是完美的,最重要的是要发挥其长处。就算有GIL我也不在乎,我还是会用Python。