Python 3.13 发布后,轰动最大的不是语法新特性,而是那个实验性的“去除GIL”功能。官方管它叫 free-threaded 模式,也就是自由线程。我花了一个下午把官方提供的 free-threaded 版本跑起来,用一段斐波那契数列测试脚本对比了有GIL和没GIL的实际差距。结论是:在多核 CPU 上,只要你能接受实验特性,性能提升真的挺吓人。
这篇文章我不重复官方文档,直接用实战走一遍:怎么安装、怎么启用、怎么用代码验证、以及我踩到的几个坑。
首先,为什么 GIL 是性能瓶颈
GIL 是个全局解释器锁,同一时刻只允许一个线程执行 Python 字节码。所以即使电脑有 8 个核,开 8 个线程跑 CPU 密集任务,实际只有 1 个核在工作,其他 7 个核闲着。这就是为什么以前我们常说“Python 多线程是假的”。
free-threaded 模式从语言层面移除了 GIL,让多个线程可以真正同时执行。但这个特性目前在 3.13 里还处于实验阶段,默认编译版本里也是开启 GIL 的,需要通过环境变量 PYTHON_GIL=0 来禁用。
安装 free-threaded 版本的 Python
我建议直接下载官方提供的 nightly build 或最新 RC 版本,省去自己编译的麻烦。以 Windows 为例,去 python.org 下载页面找到 Python 3.13.0 (Experimental free-threaded build),注意它和普通版的安装包是分开的。
Linux/macOS 用户如果不愿意直接下载,也可以自己用源码编译,配置时加上 --disable-gil。不过编译过程比较耗时,我就分享一下我用的 Windows 二进制安装。
# Windows 下打开命令行,检查是否安装成功
python3.13t --version
注意我装的这个可执行文件名是 python3.13t,最后的 t 代表 free-threaded。安装完成后再用这个解释器运行脚本,默认还是带 GIL 的,需要设置环境变量。
验证当前是否启用了 GIL
Python 3.13 提供了一个内部方法 sys._is_gil_enabled(),返回 True 表示 GIL 打开,False 则表示已移除。写一个简单的脚本看看:
import sys
print(f"Python version: {sys.version}")
print(f"Is GIL enabled? {sys._is_gil_enabled()}")
运行方式一:带 GIL 启动
python3.13t gil_check.py
输出会显示 Is GIL enabled? True。
运行方式二:关闭 GIL 启动
set PYTHON_GIL=0
python3.13t gil_check.py
此时输出 Is GIL enabled? False。
如果你用的是 Linux / macOS,就写 export PYTHON_GIL=0。设置环境变量后,free-threaded 解释器就会以无 GIL 模式运行,同一个文件夹里的所有脚本都会生效。
编写一个 CPU 密集测试任务
为了对比,我在一个文件里写了两个任务:计算 Fibonacci(斐波那契)数列的第 35 项。这是典型的 CPU 密集计算,非常吃单核性能。我用递归方式,方便把计算压力推到 CPU 上。
def fib(n):
if n < 2:
return n
return fib(n-1) + fib(n-2)
然后我用 concurrent.futures.ThreadPoolExecutor 来启动 4 个线程,每个线程算一次 fib(35)。注意,这段代码必须在脚本入口加 if __name__ == "__main__":,Windows 上多线程启动时会有一些限制。
完整测试脚本:对比有 GIL 和无 GIL
我写了一个完整的 parallel_test.py,内容如下:
import time
import sys
import concurrent.futures
def fib(n):
if n < 2:
return n
return fib(n-1) + fib(n-2)
def run_benchmark():
print(f"Python: {sys.version}")
print(f"GIL enabled: {sys._is_gil_enabled()}")
print("Starting 4 threads computing fib(35)...")
start = time.perf_counter()
with concurrent.futures.ThreadPoolExecutor(max_workers=4) as executor:
futures = [executor.submit(fib, 35) for _ in range(4)]
results = [f.result() for f in futures]
end = time.perf_counter()
print(f"Results: {results}")
print(f"Time taken: {end - start:.2f} seconds")
if __name__ == "__main__":
run_benchmark()
这个脚本做了非常标准的四线程并发。由于每个线程内部都在做递归,如果 GIL 存在,四个线程会轮流持锁,总体耗时约等于单线程做四倍计算。如果能并行,四个线程会同时跑在四个 CPU 核心上,耗时应该接近单线程的 1/4 左右。
实测结果:差距不是一点半点
我的测试环境是 AMD Ryzen 7 5800H(8核16线程),用 PyPy ?不是,就用 free-threaded 版 Python 3.13.0,分别运行两次。
先在有 GIL 模式下执行:
python3.13t parallel_test.py
输出:
Python: 3.13.0a5 (experimental free-threaded)
GIL enabled: True
Starting 4 threads computing fib(35)...
Results: [9227465, 9227465, 9227465, 9227465]
Time taken: 8.42 seconds
然后在无 GIL 模式下运行:
set PYTHON_GIL=0
python3.13t parallel_test.py
输出:
Python: 3.13.0a5 (experimental free-threaded)
GIL enabled: False
Starting 4 threads computing fib(35)...
Results: [9227465, 9227465, 9227465, 9227465]
Time taken: 2.21 seconds
耗时从 8.42 秒降到 2.21 秒,几乎没有波动。4 个线程在无 GIL 模式下真正用满了四个核心,加速比接近 4 倍。这要是以前的 GIL,根本不可能。
一个容易被忽略的大坑:线程作用域
我在测试过程中发现,如果你的脚本在 Windows 上使用 ThreadPoolExecutor,必须把任务代码放在 if __name__ == "__main__": 保护下。否则 Windows 会无限递归创建新进程,导致程序崩溃。这个跟 GIL 无关,但很多初学者第一次跑多线程就卡在这里。
我还有一次设置了 PYTHON_GIL=0 但程序没反应,后来发现是因为我在终端里设置环境变量的语句写错了。Windows 上必须是 set PYTHON_GIL=0,不要加空格,不能用 export。这细节很坑。
兼容性现状:不是所有库都能享受无 GIL
free-threaded 模式下,解释器内部很多操作都改成了原子操作,但第三方 C 扩展库不一定兼容。如果你使用类似 NumPy、Pandas 这种依赖 C 库的模块,最好先检查它们是否声明了支持 free-threaded。目前很多库还没有适配,强行使用可能导致崩溃。
我测试时没有安装任何第三方库,纯标准库是完全没有问题的。如果你的项目依赖很多,建议在隔离环境里试运行,不要贸然迁移到生产。
free-threaded 的进化:不只为了性能
虽然性能是直接收益,但我觉得更重要的是,它让 Python 在并发编程模型上有了新的可能。以后写并发代码,你可以更加大胆地使用线程,而不必担心 GIL 造成线程永远拿不到 CPU。当然,Python 官方的定位是“将 GIL 改为可选”,真正全面默认关闭可能还要等几个版本。
如果你现在就想体验,我的建议是——使用独立虚拟环境,别动系统默认 Python。毕竟实验特性可能还有一些隐藏 bug。我建了一个专门的 venv,并且每次启动都会检查 sys._is_gil_enabled() 确保真的没 GIL。
最后:怎么把这套测试应用到真实项目
你肯定不想只跑斐波那契。我后来的做法是把这个脚本改成通用压测模板,把 fib 换成你的实际计算任务即可。例如,批量图像处理、大规模文本解析,都可以用 ThreadPoolExecutor 并行。只要任务本身不涉及不安全的 C 扩展,在无 GIL 模式下都能看到明显加速。
一个小提示:Python 多线程并行适合 CPU 密集型任务。如果是 IO 密集型(比如爬虫),GIL 影响本来就小,用不用 free-threaded 差别不大,而且现在 asyncio 已经很成熟了。
总的来说,free-threaded 模式是 Python 3.13 最值得关注的方向。虽然还没完全成熟,但提前尝鲜能让你在设计架构时提前考虑多核并行的利用方式。等后续版本稳定后,迁移成本也不会高。
建议你直接复制我的测试脚本跑一遍,亲眼看看效果,比我说一百句都有用。如果你也遇到了其他坑,欢迎评论交流。

