Announcement

👇Official Account👇

Welcome to join the group & private message

Article first/tail QR code

Skip to content

Python 3.14 Free-Threading 正式支持深度解析:PEP 779 之后 GIL 时代的终结

导语

Python 官方在 3.14 系列中正式将 free-threaded(无 GIL)构建从"实验性"升级为"官方支持"——这就是 PEP 779 的落地。从 Python 3.14 开始,Global Interpreter Lock(GIL)正式成为可选项:你可以运行一个没有 GIL 的 CPython,让多线程真正并行执行。

这是 Python 语言三十年来最重要的一次运行时变革。自 1992 年 GIL 诞生起,"Python 多线程无法利用多核"就是最大的性能抱怨;如今这条路正式打通。

本文将拆解 PEP 779 的内容、free-threaded 构建的安装与使用、性能表现、C 扩展兼容性,以及它与 Python 3.14 其他重大特性(JIT、PEP 836)的关系。


一、从 PEP 703 到 PEP 779:GIL 移除的三阶段

1.1 GIL 是什么,为什么难移除

GIL 是 CPython 解释器中的一个全局互斥锁:同一时刻只有一个线程能执行 Python 字节码。它让 CPython 的内存管理(引用计数)无需加锁,代价是 CPU 密集的多线程程序无法利用多核。

移除 GIL 的难点不在锁本身,而在 CPython 遍布各处的共享可变状态:引用计数、全局缓存、内存分配器、内建类型(dict/list)的并发安全……所有 C 代码都假设"同一时刻只有一个线程碰这些状态"。

1.2 PEP 703:让 GIL 可选(2023)

PEP 703(Making the Global Interpreter Lock Optional in CPython) 于 2023 年由 Sam Gross 提出并被 Steering Council 接受。它规划了三阶段路线图:

阶段内容状态
Phase Ifree-threaded 构建可用但明确实验性完成(3.13)
Phase IIfree-threaded 构建官方支持但仍可选完成(3.14,PEP 779)
Phase IIIfree-threaded 成为默认构建未定,留给未来

关键设计:GIL 不会被删除(那会破坏整个世界),而是 CPython 提供两套二进制:标准构建(带 GIL)和 free-threaded 构建(无 GIL),后者用 t 后缀标识。

1.3 PEP 779:确立 Phase II 标准(2026)

PEP 779(Criteria for supported status for free-threaded Python) 由 Thomas Wouters、Matt Page、Sam Gross 提出,为 Phase II 定义了可量化的标准:

  • 性能:单线程性能惩罚硬性目标 15% 以内(当时实测约 10%)
  • 内存:内存使用目标 20%(pyperformance 几何均值)以内
  • API 稳定:无需激进改动现有 API(遵循 PEP 387 变更策略)
  • 文档:内部实现文档补齐

Steering Council 正式接受 PEP 779,从 Python 3.14 起移除 free-threaded 构建的 "experimental" 标签。同时提出 Phase II 期间的额外要求:C API/ABI 兼容性必须与 C API 工作组事先沟通,并期望 3.15 准备好 Stable ABI 支持


二、3.14 Free-Threading 的实际改进

2.1 从"能跑"到"好用"

PEP 703 描述的 free-threaded 实现在 3.14 中已经全部完成,包括 C API 变更,解释器中的临时 workaround 被永久方案替代。最关键的改进:

The specializing adaptive interpreter (PEP 659) is now enabled in free-threaded mode, which along with many other optimizations greatly improves its performance.

PEP 659 自适应特化解释器(JIT 的前置优化)在 free-threaded 模式下启用了。 这带来巨大性能提升——free-threaded 模式不再是"阉割版"解释器。

2.2 单线程性能惩罚

官方数据:free-threaded 模式下单线程代码性能惩罚约 5-10%(取决于平台和 C 编译器)。相比 PEP 779 设定的 15% 硬性目标,实测表现优于目标

这个惩罚的来源:无 GIL 环境下,引用计数等操作需要原子操作/偏置计数,比普通构建多一点点开销。

2.3 其他改进

  • -X context_aware_warnings:控制并发安全的 warnings 处理;free-threaded 构建默认开启,GIL 构建默认关闭
  • thread_inherit_context:新标志,线程创建时继承调用方的 Context();free-threaded 构建默认开启——影响 catch_warningsdecimal 上下文等
  • Windows 构建:编译 free-threaded 的 C 扩展时,Py_GIL_DISABLED 需由构建后端显式指定(不再自动推断),运行时可用 sysconfig.get_config_var() 查询

三、安装与使用:3.14t 构建

3.1 获取 free-threaded Python

官方下载页提供 free-threaded 预编译二进制,标识为 t 后缀:

Windows(Python Install Manager):

bash
py install 3.14t
py install 3.14t-arm64
py install 3.14t-32

安装后可用 py -V:3.14tpython3.14t.exe 启动。若系统只有这一个运行时,python 命令会直接指向它。

macOS / Linux:官方安装器在自定义安装选项中提供 free-threaded 二进制。

3.2 验证是否无 GIL

python
import sys
print(sys._is_gil_enabled())   # False = free-threaded(无 GIL)

3.3 简单示例

python
import threading
import time

def work(n):
    total = 0
    for i in range(n):
        total += i * i
    return total

start = time.perf_counter()
threads = [threading.Thread(target=work, args=(5_000_000,)) for _ in range(4)]
for t in threads: t.start()
for t in threads: t.join()
print(f"4 线程耗时: {time.perf_counter() - start:.2f}s")

在有 GIL 的 Python 中,这段纯计算代码 4 个线程串行执行(GIL 竞争);在 free-threaded 构建中,4 个线程真正并行,多核机器上接近 4 倍加速。


四、C 扩展生态:最大的现实约束

free-threading 落地最大的风险不在解释器本身,而在海量的 C 扩展——它们大多按"有 GIL"假设编写。

4.1 现状

  • 3.13 实验性阶段,社区已有显著采用:大量第三方库已适配 free-threaded(声明线程安全)
  • 官方确认:现有 API 无需激进修改即可适配,未出现破坏性变更
  • Stable ABI 在 3.15 准备——届时支持 Stable ABI 的 wheel 可同时用于两种构建,分发问题大幅缓解

4.2 对项目的影响

依赖类型状态
纯 Python 库完全兼容,无需修改
已适配的 C 扩展(如部分 NumPy 生态)可运行
未适配的 C 扩展可能崩溃或回退到 GIL 模式(视实现)

4.3 官方建议

If you're running production systems with complex C extension dependencies, stay on 3.13 for now.

生产环境有复杂 C 扩展依赖的,暂时留在 3.13——3.13 完全支持,不急迁移。新项目则可以直接用 3.14(含 JIT 默认开启)。


五、与 JIT 的协同:Python 性能新时代

5.1 3.14 的 JIT 状态

Python 3.14 的 JIT 编译器(基于 PEP 836,即 "JIT Go Brrr")在 x86-64 和 ARM64 上默认开启,pyperformance 基准中位数性能提升 12-18%(无需改代码)。

5.2 两者的关系

这里有一个关键背景:JIT 与 free-threading 曾被认为冲突此前的治理危机中,Steering Council 要求 JIT 在 3.16/3.17 分别达到 GIL 构建与 free-threading 构建的提速目标)。3.14 中:

  • GIL 构建:JIT 默认开启,12-18% 提速
  • free-threaded 构建:PEP 659 特化解释器已启用,性能惩罚收窄到 5-10%

两条路线在 3.14 都取得了实质进展,为 3.16/3.17 的 JIT+free-threading 全速目标铺路。

5.3 性能全景(3.14)

构建JIT单线程相对基线多线程
标准(GIL)默认开启+12-18%受 GIL 限制
free-threaded(3.14t)PEP 659 启用-5-10%真并行,多核可扩展

六、什么时候切换到 Free-Threading

6.1 适合现在就切

  • 新项目:无历史包袱,直接 3.14t
  • CPU 密集 + 多线程 + 依赖简单:纯 Python 或已适配库,收益明显
  • I/O 密集 + 已有 asyncio:asyncio 本身就规避了 GIL 问题,迁移收益有限但无风险

6.2 建议等待

  • 生产系统 + 复杂 C 扩展依赖:等 3.15 Stable ABI + 生态适配完成
  • 对结果可复现性有硬性要求:free-threading 下浮点/哈希等行为可能因并行而略有差异
  • 依赖未适配的二进制库:先验证依赖清单

6.3 迁移清单


七、Phase III:默认化的未定之局

PEP 779 明确划清界限:Phase III(free-threading 成为默认)尚未决定

未来的决策将围绕:

  • 社区支持度与采用率
  • 性能/内存的长期平衡(Phase III 的性能目标需要社区重新定义)
  • Stable ABI 成熟度
  • C 扩展生态的适配进度

官方态度是"留到未来"——这意味着至少未来几个版本内,GIL 构建仍是默认,开发者可以按需选择,无需担心强制迁移。


八、总结

Python 3.14 的 free-threading 正式支持(PEP 779)是语言史上的一座里程碑:

  • GIL 成为可选项3.14t 构建官方支持,多线程真并行成为可能
  • 性能达标:单线程惩罚 5-10%,优于 PEP 779 的 15% 硬性目标;PEP 659 特化解释器已在 free-threaded 模式启用
  • 生态逐步跟进:Stable ABI 定于 3.15 准备,C 扩展适配在加速
  • 默认未变:Phase III 未定,GIL 构建仍是默认,迁移主动权在开发者

三十年的 GIL 争论,从"已知限制"变成了"可选开关"。 对追求多核性能的开发者,2026 年是值得尝试的一年:新项目上 3.14t,生产系统稳守 3.13/3.14 标准构建,等生态成熟再全面切换。


参考来源

上次更新于: