Python如何规避全局解释器锁(GIL)带来的限制

Posted WESWES

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python如何规避全局解释器锁(GIL)带来的限制相关的知识,希望对你有一定的参考价值。

 

编程语言分类概念介绍(编译型语言、解释型语言、静态类型语言、动态类型语言概念与区别)

https://www.cnblogs.com/zhoug2020/p/5972262.html

 

Python解释器

一般使用的Python解释器CPython:是用C语言实现Pyhon,是目前应用最广泛的解释器。最新的语言特性都是在这个上面先实现,基本包含了所有第三方库支持,但是CPython有几个缺陷,一是全局锁使Python在多线程效能上表现不佳,二是CPython无法支持JIT(Just-in-time compliation即时编译),导致其执行速度不及Java和Javascipt等语言。于是出现了Pypy。

Pypy:是用Python自身实现的解释器。针对CPython的缺点进行了各方面的改良,性能得到很大的提升。最重要的一点就是Pypy集成了JIT。但是,Pypy无法支持官方的C/Python API,导致无法使用例如Numpy,Scipy等重要的第三方库。(还有JPython,IronPython等)

 

全局解释器锁

全局解释器锁(Global Interpreter Lock)是Python用于同步线程的工具,使得任何时刻仅有一个线程在执行。 

 

Python GIL被动释放机制(抢占机制)

如果一个线程不间断地在 Python 2 中运行100次解释器的计步(ticks)(可以通过sys.setcheckinterval()设置计步长度),或者不间断地在 Python 3 运行15 毫秒,那么它便会放弃 GIL,而其他线程可以运行。

 

全局解释器锁带来的问题

多线程Python程序无法充分利用多个CPU核心带来的优势。

(主要影响CPU密集型程序,I/O密集型程序使用多线程一般是明智的选择)

 

解决方法

1,使用多进程

原理:每个进程分配不同的解释器,有单独的GIL。

缺点:额外产生数据序列化与通信的开销。

注意点:待执行操作需包含在以def语句定义的Python函数中(即,在这里lambda,闭包,可调用实例都是不可以的),而且函数参数和返回值必须兼容pickle编码。

使用方法:廖雪峰Python教程-多进程部分

 

2,使用C语言扩展模块

原理:C语言扩展程序的执行保持与Python解释器隔离,在C代码中释放GIL。

缺点:调用C函数时GIL会被锁定,若阻塞,解释器无法释放GIL。

注意点:确保C代码可以独立于Python执行。(不使用Python的数据结构,也不调用Python的C语言API)

使用方法:在C代码中插入特殊的宏或是使用其他工具来访问C代码,如ctypes库或者Cython。(ctypes默认会在调用C代码时自动释放GIL)

使用ctypes访问C代码教程

 

3,选用其他没有GIL的解释器代替CPython

原理:使用没有GIL的解释器实现。

缺点:不完全兼容。

使用方法:目前Jython和IronPython没有GIL。

Jython文档IronPython官网

 

以上是关于Python如何规避全局解释器锁(GIL)带来的限制的主要内容,如果未能解决你的问题,请参考以下文章

python并发之multiprocessing

Python全局解释器锁(GIL)

Python 36 GIL全局解释器锁

深入理解Python中的GIL(全局解释器锁)

python GIL全局解释器锁与互斥锁 目录

Python 之 GIL 全局解释器锁