当前位置:首页>python>GIL终于死了:Python等了35年的"自由",到底是什么?

GIL终于死了:Python等了35年的"自由",到底是什么?

  • 2026-10-12 12:15:43
GIL终于死了:Python等了35年的"自由",到底是什么?

"

【嗨翻Python】Python前沿观察

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到底快多少?

01

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利用率: 多个核心同时干活

02

SECTION 02

free-threading不是"一夜之间"来的:从实验到生产的三步走

很多人以为free-threading是突然冒出来的。其实Python核心团队花了三个版本,一步步把这件事做稳了。

版本时间状态关键变化
Python 3.132024年10月实验性支持首次引入free-threaded build,需要编译时特殊配置,不稳定,API随时可能变
Python 3.142025年10月官方正式支持free-threaded build成为官方选项,第三方包开始适配,生态逐步跟进
Python 3.152026年8月稳定ABI,production-readyfree-threading的ABI稳定,不再变动,官方推荐生产环境使用

这三步的逻辑很清晰:

3.13:先放出来让大家试试,发现问题

3.14:官方背书,生态跟进

3.15:接口冻结,可以放心用了

这是一次教科书级的"渐进式架构升级"。 没有一刀切地移除GIL(那样会炸掉无数现有项目),而是给了一个可选的build模式,让生态有时间适配。

03

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.0xGIL限制,多线程几乎没用
Python 3.13 free-threaded12.8秒5.1秒2.5x实验版,有加速但不稳定
Python 3.14 free-threaded12.5秒3.2秒3.9x官方支持,生态适配中
Python 3.15 free-threaded12.4秒1.3秒9.5x稳定版,接近理论极限

关键发现:

有GIL时:8个线程和1个线程速度几乎一样——这就是GIL的"罪证"

free-threading后:加速比逐版本提升,3.15达到了接近8核的理论上限

单线程性能代价:free-threaded模式的单线程性能有约1%-8%的轻微下降(上表中12.4 vs 12.3),这是为多线程自由付出的"保险费用"

04

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模式下可能出现数据竞争、崩溃

生产环境稳定运行 > 追新

05

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上开发,要格外注意测试。

06

SECTION 06

现在到底要不要升级?

给一个清晰的决策树:

CODE

你的项目是什么类型?

│

├── 纯Python项目,不依赖C扩展

│   └── ✅ 可以升级到3.15,享受free-threading

│

├── Web服务(Django/Flask/FastAPI)

│   └── ✅ 框架已支持,但检查所有依赖包兼容性

│

├── 数据科学/机器学习

│   └── ⏳ 再等等,NumPy/SciPy生态适配尚未完成

│

├── 重度依赖C扩展

│   └── ❌ 暂不升级,等依赖包适配

│

└── 生产环境,追求稳定

    └── ⏳ 等3.15正式版(非RC),跑完全部回归测试再升

我的具体建议:

1

学习/个人项目:现在就用Python 3.15 free-threaded版本,体验真正的多线程

2

新项目:如果有多线程需求,直接用3.15起步

3

老项目:先在CI/CD中加一个free-threaded的测试矩阵,看兼容情况

4

生产环境:等3.15正式版发布(RC1之后通常1-2个月),确认所有依赖兼容后再迁移

07

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扩展依赖、极致单线程性能需求
08

SECTION 08

一个时代的结束

1991年,Guido发布Python 0.9时,大概没想到GIL会成为Python最持久的争议话题。

35年来,社区 tried everything:

multiprocessing绕道

Jython/IronPython无GIL实现(但生态不兼容)

asyncio异步方案(I/O可以,CPU还是不行)

各种subprocess黑魔法

现在,Python选择了一条最难但最正确的路:不是移除GIL,而是给你一个"没有GIL的选项"。

这很Python——向后兼容,渐进演进,不打破现有世界。

对于普通开发者来说,你不需要今天就做什么。但你必须知道:Python的并发能力,从此不一样了。

当你的项目需要真正的多线程并行时,不用再绕路了。

09

SECTION 09

行动清单

[ ] 安装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仍在快速演进中,具体特性以官方文档为准。

END

最新文章

随机文章