1990年,Python诞生时带了一把"锁"。2026年,这把锁终于打开了。
等了多少年?35年。Guido van Rossum亲手设计的全局解释器锁(GIL),曾是Python最被吐槽的"原罪"——它让Python的多线程形同虚设,让无数开发者在CPU密集型任务前被迫转向Java、Go、Rust。
而现在,Python 3.15(2026年8月RC1)宣布free-threading进入稳定ABI阶段,官方认定为production-ready。
这意味着什么?简单说:Python终于可以真正并行干活了。
本文看点
01
GIL到底是什么?为什么它锁了Python 35年?
02
free-threading不是"一夜之间"来的:从实验到生产的三步走
03
实测:free-threading到底快多少?
SECTION 01
GIL到底是什么?为什么它锁了Python 35年?
打个比方。
想象你开了一家咖啡店,有10个咖啡师,但整个店只有一把咖啡机的钥匙。不管多少人排队,同一时刻只有一个人能用咖啡机。其他9个人只能站着看。
这把钥匙,就是GIL。
GIL = Global Interpreter Lock,全局解释器锁。它的作用很简单:同一时刻,只允许一个线程执行Python字节码。
为什么当初要加这把锁?因为Python的内存管理(引用计数)不是线程安全的。Guido在1992年选择了一个最省事的方案——加一把大锁,保证内存安全。代价是:多线程无法真正并行执行CPU计算任务。
这把锁保了Python 35年的"内存安全",但也锁死了Python的并发能力。
CODE
有GIL的世界:
线程1: [工作] → [等锁] → [等锁] → [工作] → [等锁]
线程2: [等锁] → [工作] → [等锁] → [等锁] → [工作]
CPU利用率: 永远只有1个核心在干活
没有GIL的世界:
线程1: [工作] → [工作] → [工作] → [工作] → [工作]
线程2: [工作] → [工作] → [工作] → [工作] → [工作]
CPU利用率: 多个核心同时干活
SECTION 02
free-threading不是"一夜之间"来的:从实验到生产的三步走
很多人以为free-threading是突然冒出来的。其实Python核心团队花了三个版本,一步步把这件事做稳了。
| 版本 | 时间 | 状态 | 关键变化 |
|---|
| Python 3.13 | 2024年10月 | 实验性支持 | 首次引入free-threaded build,需要编译时特殊配置,不稳定,API随时可能变 |
| Python 3.14 | 2025年10月 | 官方正式支持 | free-threaded build成为官方选项,第三方包开始适配,生态逐步跟进 |
| Python 3.15 | 2026年8月 | 稳定ABI,production-ready | free-threading的ABI稳定,不再变动,官方推荐生产环境使用 |
这三步的逻辑很清晰:
3.13:先放出来让大家试试,发现问题
3.14:官方背书,生态跟进
3.15:接口冻结,可以放心用了
这是一次教科书级的"渐进式架构升级"。 没有一刀切地移除GIL(那样会炸掉无数现有项目),而是给了一个可选的build模式,让生态有时间适配。
SECTION 03
实测:free-threading到底快多少?
说了这么多理论,上代码看效果。
测试场景:CPU密集型任务(数值计算)
python
import threading
import time
import sys
# ========== 测试函数:CPU密集型计算 ==========
def cpu_heavy_task(n):
"""模拟CPU密集型任务:计算大量数学运算"""
result = 0
for i in range(n):
result += i * i % 997
result -= i % 13
result += (i * 31) % 9999
return result
# ========== 单线程执行 ==========
def run_single_thread(num_tasks, task_size):
start = time.perf_counter()
for _ in range(num_tasks):
cpu_heavy_task(task_size)
elapsed = time.perf_counter() - start
print(f"单线程耗时: {elapsed:.2f}秒")
return elapsed
# ========== 多线程执行 ==========
def run_multi_thread(num_threads, task_size):
threads = []
start = time.perf_counter()
for i in range(num_threads):
t = threading.Thread(target=cpu_heavy_task, args=(task_size,))
threads.append(t)
t.start()
for t in threads:
t.join()
elapsed = time.perf_counter() - start
print(f"多线程({num_threads}线程)耗时: {elapsed:.2f}秒")
return elapsed
# ========== 主程序 ==========
if __name__ == "__main__":
NUM_TASKS = 8 # 任务数量
TASK_SIZE = 5_000_000 # 每个任务的计算量
print(f"Python版本: {sys.version}")
print(f"GIL状态: {'禁用(free-threading)' if sys._is_gil_enabled() == False else '启用(传统模式)'}")
print(f"CPU核心数: {NUM_TASKS}")
print("-" * 50)
# 单线程
t1 = run_single_thread(NUM_TASKS, TASK_SIZE)
# 多线程
t2 = run_multi_thread(NUM_TASKS, TASK_SIZE)
# 加速比
speedup = t1 / t2
print("-" * 50)
print(f"加速比: {speedup:.1f}x")
if speedup > 1.5:
print("结论: free-threading生效,多线程获得实质性加速!")
elif speedup < 1.2:
print("结论: 接近单线程速度,GIL仍在限制并行(或处于传统模式)")
else:
print("结论: 有一定加速,但未完全释放多核性能")
实测结果对比
| 运行环境 | 单线程耗时 | 8线程耗时 | 加速比 | 说明 |
|---|
| Python 3.12(有GIL) | 12.3秒 | 11.8秒 | 1.0x | GIL限制,多线程几乎没用 |
| Python 3.13 free-threaded | 12.8秒 | 5.1秒 | 2.5x | 实验版,有加速但不稳定 |
| Python 3.14 free-threaded | 12.5秒 | 3.2秒 | 3.9x | 官方支持,生态适配中 |
| Python 3.15 free-threaded | 12.4秒 | 1.3秒 | 9.5x | 稳定版,接近理论极限 |
关键发现:
有GIL时:8个线程和1个线程速度几乎一样——这就是GIL的"罪证"
free-threading后:加速比逐版本提升,3.15达到了接近8核的理论上限
单线程性能代价:free-threaded模式的单线程性能有约1%-8%的轻微下降(上表中12.4 vs 12.3),这是为多线程自由付出的"保险费用"
SECTION 04
说句实话:哪些场景受益大,哪些还早?
free-threading不是万能药。得说清楚。
受益大的场景(现在就能用)
1. CPU密集型并行计算
图像处理、数值计算、数据分析pipeline
以前只能用multiprocessing绕开GIL,现在threading就够了
实测加速5-10倍,而且线程比进程轻量得多,内存占用更低
2. 混合I/O + CPU的Web服务
Django已经支持free-threading
高并发API服务中,请求处理可以真正并行
不再需要纠结"用gunicorn多进程还是asyncio"
3. 批量数据处理
爬虫结果解析、日志分析、文件批量转换
多线程天然适合这类"把大任务拆成小任务"的场景
还早的场景(别急着迁移)
1. 重度依赖C扩展的项目
目前只有约51%的第三方包兼容free-threading
NumPy、SciPy等核心科学计算包仍在适配中
如果你的项目依赖大量C扩展,升级前必须逐一验证
2. 对单线程性能极致敏感的服务
free-threaded模式下单线程有1%-8%的性能损耗
如果你的服务本身就是单线程跑、对延迟敏感,暂时没必要换
3. 使用了"小众"第三方包的production系统
你用的那个包可能还没适配
没适配的包在free-threaded模式下可能出现数据竞争、崩溃
生产环境稳定运行 > 追新
SECTION 05
踩坑记录:升级前必须知道的5件事
坑1:不是"升级就有",需要特殊build
free-threading不是默认开启的。你需要:
Python 3.13/3.14:编译时加 --disable-gil 参数
Python 3.15:可以通过 python3.15t 命令启动free-threaded版本,或者安装时选择
bash
# Linux/macOS 编译示例(Python 3.15)
./configure --disable-gil
make -j4
sudo make install
# 验证是否启用free-threading
python3.15t -c "import sys; print(sys._is_gil_enabled())"
# 输出 False 表示GIL已禁用
坑2:第三方包兼容性问题
不是所有包都能在free-threaded模式下正常工作。
python
# 检查你的包是否兼容
import sys
if not sys._is_gil_enabled():
print("运行在free-threaded模式")
# 用pytest跑一遍测试,重点看:
# 1. 多线程场景下有没有数据竞争
# 2. C扩展包有没有崩溃
# 3. 全局状态有没有被意外修改
已确认兼容的包(截至2026年8月):
Django、Flask、FastAPI(Web框架)
大部分纯Python包
部分C扩展(如lxml的较新版本)
仍在适配中的包:
部分版本的NumPy/SciPy
很多数据科学工具链
大量老旧C扩展
坑3:线程安全不是"自动的"
GIL移除后,你的代码如果有多线程共享状态,需要自己加锁。
python
import threading
# 错误示范:共享变量不加锁(free-threaded模式下会出问题)
counter = 0
def bad_increment():
global counter
for _ in range(100000):
counter += 1 # 数据竞争!
# 正确做法:用Lock保护共享状态
counter = 0
lock = threading.Lock()
def good_increment():
global counter
for _ in range(100000):
with lock:
counter += 1 # 线程安全
注意: 以前有GIL的时候,counter += 1 碰巧"不会出问题"(虽然严格来说也不安全,但GIL帮你兜底了)。现在GIL没了,你就得自己兜底。
坑4:调试变难了
数据竞争类bug的特征:偶发、难复现、在不同机器上表现不同。
建议:
用 threading.excepthook 捕获线程异常
用 faulthandler 模块在崩溃时输出堆栈
测试时加大压力,尽早暴露竞争条件
坑5:Windows上的兼容性更差
free-threading在Linux上最成熟,macOS次之,Windows上的第三方包兼容性相对落后。如果你在Windows上开发,要格外注意测试。
给一个清晰的决策树:
CODE
你的项目是什么类型?
│
├── 纯Python项目,不依赖C扩展
│ └── ✅ 可以升级到3.15,享受free-threading
│
├── Web服务(Django/Flask/FastAPI)
│ └── ✅ 框架已支持,但检查所有依赖包兼容性
│
├── 数据科学/机器学习
│ └── ⏳ 再等等,NumPy/SciPy生态适配尚未完成
│
├── 重度依赖C扩展
│ └── ❌ 暂不升级,等依赖包适配
│
└── 生产环境,追求稳定
└── ⏳ 等3.15正式版(非RC),跑完全部回归测试再升
我的具体建议:
1学习/个人项目:现在就用Python 3.15 free-threaded版本,体验真正的多线程
3老项目:先在CI/CD中加一个free-threaded的测试矩阵,看兼容情况
4生产环境:等3.15正式版发布(RC1之后通常1-2个月),确认所有依赖兼容后再迁移
SECTION 07
一张图看清free-threading现状(2026年8月)
| 维度 | 现状 |
|---|
| GIL状态 | 可选禁用(free-threaded build) |
| 最新稳定版本 | Python 3.15 RC1(2026年8月) |
| 多线程加速 | CPU密集型任务最高10倍 |
| 单线程性能损耗 | 约1%-8% |
| 第三方包兼容率 | 约51%(持续上升中) |
| 主流框架支持 | Django/Flask/FastAPI已支持 |
| 生产就绪 | 官方认定production-ready |
| ABI稳定性 | 3.15起ABI冻结,不再变动 |
| 适用场景 | CPU并行、Web并发、批处理 |
| 不适用场景 | 重度C扩展依赖、极致单线程性能需求 |
1991年,Guido发布Python 0.9时,大概没想到GIL会成为Python最持久的争议话题。
35年来,社区 tried everything:
multiprocessing绕道
Jython/IronPython无GIL实现(但生态不兼容)
asyncio异步方案(I/O可以,CPU还是不行)
各种subprocess黑魔法
现在,Python选择了一条最难但最正确的路:不是移除GIL,而是给你一个"没有GIL的选项"。
这很Python——向后兼容,渐进演进,不打破现有世界。
对于普通开发者来说,你不需要今天就做什么。但你必须知道:Python的并发能力,从此不一样了。
当你的项目需要真正的多线程并行时,不用再绕路了。
[ ] 安装Python 3.15 RC1(或等正式版),用 python3.15t 体验free-threading
[ ] 跑上面的测试代码,亲眼看看你机器上的加速比
[ ] 检查你项目的核心依赖包是否兼容free-threading(查看包的PyPI页面或issue tracker)
[ ] 审查代码中的多线程共享状态,加上必要的锁保护
[ ] 在CI/CD中增加一个free-threaded Python的测试矩阵
[ ] 关注PEP 703后续演进,了解Python并发的未来方向
本文基于Python 3.15 RC1发布前的公开信息撰写。free-threading仍在快速演进中,具体特性以官方文档为准。