去年的2022 Python 语言峰会上,开发者 Sam Gross 带来了新提案:删除全局解释器锁 GIL,解放多线程性能。但由于 GIL 历史悠久,许多官方/非官方的 Python 包和模块都深度融合了 GIL 模块,彻底移除 GIL 功能可能会对生态造成影响。在 2023 年 1 月 9 日, Sam Gross 又创建了另一个 Python 提案 PEP 703:使全局解释器锁成为构建 Python 的可选项。
CPython 的全局解释器锁(“GIL”)防止多个线程同时执行 Python 代码,GIL 是 Python 有效使用多核 CPU 的障碍。
向 CPython 添加一个构建配置 (
--without-gil
) ,使其可在没有全局解释器锁的情况下运行 Python 代码,并进行必要的更改,以使解释器线程安全。
这条 PEP 提案的内容可谓是论文级别。提案中先阐述了 GIL 对 Python 并发的性能阻碍,随后详细分析了抽离 GIL 需要对 Python 内部进行哪些改动:
移除全局解释器锁需要对 CPython 内部进行大量更改,但对公共 Python 和 C API 的更改相对较少。
实施的变更大约分为以下四类:
引用计数、内存管理、容器线程安全、锁和 atomic API
由于该提案内容实在太多,感兴趣的朋友请在 PEP 703 详情页和 Cpython 核心开发者对该提案的讨论帖中细阅。
目前此 PEP 已经有了参考实现,它的原型源于当初为了移除 GIL 而开发的 nogil 项目,该原型对单线程代码带来较明显 (~10%) 性能提升。
如果该提案通过,意味着默认情况下 CPython 不会删除或关闭 GIL,也不会让用户有选择地启用/删除 GIL。因为--without-gil
是一个编译时标志,可以在从源代码构建 Python 解释器时进行设置。但如果弃用该配置,会导致对解释器的构建和运行方式的深度侵入性更改,PEP 中也对此进行了详细介绍。
对用户侧来说,该改动意味着如果用户使用任何带有编译扩展的包,将需要获取或构建一个专门针对 Python 解释器的(不同的)ABI 编译的版本,该版本在没有 GIL 的情况下编译。
关于 Python GIL
由于 CPython 的内存管理非线程安全,因此设计了 CPython 的 GIL (Global Interpreter Lock - 全局解释器锁),以防止竞争条件并确保线程安全。 GIL 是一个互斥锁,只允许一个线程持有 Python 解释器的控制权,从而保护对 Python 对象的访问,防止多个线程同时执行 Python 字节码。
但事后看来,GIL 并不理想,因为它阻止了多线程的 CPython 程序充分利用多核处理器的性能。