首页 › programming › 锁了三十年,GIL终于谢幕

锁了三十年,GIL终于谢幕:一条15年前的Python神课,正在被2026年重新翻开

概述

2025年10月,Python 3.14 正式发布,free-threading(自由线程)从“实验特性”转为“官方支持”——这意味着统治 CPython 三十多年的全局解释器锁(GIL),第一次有了非实验性质的替代形态。消息传开的这一周,海外技术社区里被反复翻出来重读的,不是某篇新论文,而是 David Beazley 2010 年在 PyCon 上的经典演讲 《Understanding the GIL》。这条视频把“GIL 是什么、为什么存在、为什么难拆、拆了要付出什么”讲成了一场结构严密的推理剧:十五年过去,它依然是理解这场 Python 史上最大架构变迁的最佳入口。本文带你完整消化这条演讲,再接上它之后的十五年技术史——看完你会发现,今天新闻里的每一个关键词,都能在这条老视频里找到伏笔。

说明:本轮编辑环境联网受限,未能实时抓取视频页面,播放量等时效性数据从略,以频道页面为准;视频本身为 PyCon 官方存档的公开演讲,内容稳定,以下解读基于演讲全文。

视频基本信息

项目 内容
标题 Understanding the GIL(理解全局解释器锁)
演讲者 David Beazley(《Python Essential Reference》作者、SWIG 作者,曾任芝加哥大学计算机系教职)
场合 PyCon US 2010(亚特兰大),时长约45分钟
发布 2010 年,由 PyCon 相关官方存档频道上传 YouTube(本轮未能核验直链与播放数据)
热度 Python 社区公认的“必看经典”,每逢 GIL 相关大新闻都会被重新翻热,本轮即因 3.14 free-threading 转正再度进入各大技术周刊

核心主张拆解

Beazley 这场演讲的厉害之处在于:他不是在“介绍一个知识点”,而是在带你做一次完整的工程推理。全片按“为什么要有它→它的代价有多大→历史上有过哪些挣扎→真正的出路在哪”四幕推进。

第一幕:GIL 为什么存在——为了保护引用计数

CPython 的内存管理靠引用计数:每个对象头上记着“当前有多少个名字指着我”,计数归零就立刻回收。这个机制简单、高效、实时,代价是 refcount 这个字段会被极高频率地读写。一旦两个线程同时执行 n = n + 1 这样的语句,字节码层面是“读旧值→加一→写回”三步,中间任何一步被打断,计数就可能被写坏——轻则内存泄漏,重则直接崩溃。

主流语言的做法是给每个对象配细粒度锁,或者彻底换一套垃圾回收算法。CPython 的选择简单粗暴得多:加一把全局大锁,保证任何时刻只有一个线程在执行 Python 字节码。这就是 GIL。它本质上不是“Python 的线程是假的”,而是“线程是真的,只是轮流执行”。Beazley 强调,这个设计在单核时代几乎是最优解:锁竞争成本极低,单线程速度不受拖累,解释器实现也简单。

第二幕:代价现场演示——多核时代的羞辱

演讲最著名的一段是现场实验:让多个线程各自跑一个纯 CPU 计算循环。直觉上,双核机器两个线程应该快一倍。结果恰恰相反——两个线程比单线程串行还慢。原因在 Python 2 的切换机制:解释器每执行约 100 条指令(即 sys.setcheckinterval 的默认值)就强制当前线程让出 GIL,而让出与抢回之间的锁竞争,在多核 CPU 上会触发“抢锁风暴”——一个线程刚松手,另一个核上的线程立刻醒来抢锁,反复拉扯,大量时间浪费在协调而非计算上。

与之对照,I/O 密集型任务(网络请求、文件读写)表现正常,因为线程在发起 I/O 时会主动释放 GIL,别的线程得以运行。由此得出那条经典结论:GIL 不影响 I/O 并发,只卡死 CPU 并行。

第三幕:新 GIL 的“车队效应”

2009 年前后,社区对 GIL 的不满达到顶点,Antoine Pitrou 重写了 GIL(后随 Python 3.2 落地),把“按指令数切换”改成“按时间片切换”——默认每 5 毫秒强制让出一次(今天的 sys.setswitchinterval 就是这个遗产)。Beazley 在演讲及其后续的博客分析里,用一张张锁状态时序图把新 GIL 的病理讲得纤毫毕现:其中最著名的是车队效应(convoy effect)——一个 I/O 线程醒来想拿锁,而持锁的 CPU 线程必须“恰好”在时间片边缘让出;若没赶上,I/O 线程只能干等下一个 5 毫秒,于是多个线程像追不上头车的车队一样排队空转。他当时的结论近乎宣判:换锁策略只能缓解,不能根治——GIL 的病根在引用计数,不在锁本身。

第四幕:出路清单——15 年前的伏笔

演讲结尾,Beazley 列出了当时所有“绕开 GIL”的路径,并逐一点评:

  1. multiprocessing 多进程(Python 2.6 起内置):每个进程独立解释器、独立 GIL,用进程隔离换真并行,代价是进程间通信与序列化开销;
  2. C 扩展下沉:把热点计算放进 C/C++ 扩展,进入原生代码后主动放锁——NumPy 就是最大受益者,所以“Python 数值计算慢”这个刻板印象早就该更新了;
  3. 换一个没有 GIL 的解释器:Jython、IronPython 天生无 GIL;PyPy 则走软件事务内存(STM)的实验路线。

他最后留下的开放问题正是全片题眼:真要去掉 GIL,要么给对象加细粒度锁(性能崩塌),要么换掉引用计数(工程量浩大)。这个问题,社区用了整整十三年才给出答案。

知识与理论溯源

演讲的知识底盘全部来自真实的系统编程理论,这也是它十五年不过时的原因:

批判性审查

证据充分的部分:GIL 为引用计数而生、I/O 密集不受影响、CPU 密集无法并行——这三条是 CPython 行为的可复现事实,有官方文档与十五年的社区实测背书,演讲的演示方法至今可亲手复现。

需要修正的误读:

  1. “演讲基于 2010 年的 Python,数字已过时”——对。100 条指令的 check interval 只存在于 Python 2;3.2 起已是 5 毫秒时间片。看这条视频要抓机制逻辑,不要背具体参数。
  2. “GIL 让 Python 多线程没用”——夸大。I/O 并发一直是多线程的合法主场;大量 C 扩展(NumPy、哈希、压缩、各类数据库驱动)在进入原生代码时都会放锁。被 GIL 卡死的只是“纯 Python 代码的 CPU 并行”这一格。
  3. “3.14 之后 GIL 已经没了”——最常见的错误结论。PEP 779 的“官方支持”不等于“默认启用”:不带 GIL 的构建与带 GIL 的构建将长期并存,迁移期以年计,C 扩展生态的适配才是真正的长尾。
  4. “去 GIL 后性能白赚”——不成立。free-threaded 构建在单线程负载上仍有可测损耗(官方目标是压进个位数百分比),多核扩展比也依赖负载形态。用它之前先跑自己的基准,而不是看演示视频下结论。

一句话总结这条演讲的可信度:机制层面的论断十五年全对,具体参数需要按版本更新,结论层面它准确预言了后来所有弯路。

认知提升与实用启示

  1. 先分辨负载类型,再谈并发方案——这是本演讲给你的最实用决策树。CPU 密集:优先 NumPy 等原生扩展下沉,或 multiprocessing,2026 年起可在测试环境评估 free-threaded 构建;I/O 密集:线程、asyncio 依旧是最省心答案。“我的程序到底在等 CPU 还是在等 I/O”,应该成为每个并发 bug 排查的第一问。
  2. 学“第一手讲解者”的经典,而不是二手热点——Beazley 在 2010 年讲清的机制,让一个人能无痛理解 2025-2026 年的全部 PEP 争论。识别一手讲解者有个简单特征:他们从“这个设计为什么存在”讲起,而不是从“怎么用”讲起。技术栈变化越快,这种资产的复利越惊人。
  3. 关注迁移期红利——对库作者而言,按官方迁移指南让 C 扩展声明“不依赖 GIL”,是未来两年 Python 生态里确定性很高的技术投资;对使用者而言,把“是否 free-threading ready”纳入选型评估,会在 2027 年后持续产生回报。

Mermaid:演讲论证结构与十五年后续

flowchart TD
    A[GIL为何存在] --> B[引用计数需要保护]
    B --> C[一把全局大锁]
    C --> D[代价: CPU并行被卡死]
    D --> E[三条经典绕路]
    E --> E1[multiprocessing]
    E --> E2[C扩展下沉放锁]
    E --> E3[Jython等无GIL实现]
    D --> F[拔锁尝试屡屡失败]
    F --> G[gilectomy 2016]
    G --> H[证明必须改内存管理]
    H --> I[PEP703 偏置引用计数]
    I --> J[3.13 实验构建]
    J --> K[PEP779 官方支持]
    K --> L[3.14 双构建并存]

延伸阅读

  1. Python 官方文档《Free-threaded CPython》指南(docs.python.org/3/howto/free-threading.html)——free-threading 的官方语义、扩展迁移步骤与已知限制,本文结论部分的权威依据。
  2. PEP 703 全文及其 FAQ 章节——去 GIL 的技术选型论证(为什么是偏置引用计数而不是细粒度锁),工程决策文档的教科书级范本。

参考来源

  1. PEP 703 – Making the Global Interpreter Lock Optional in CPython — 去 GIL 提案全文:偏置引用计数等核心设计与指导委员会决策记录
  2. PEP 779 – Official support of free-threaded Python — free-threading 从实验转官方支持的分阶段路线
  3. Free-threaded CPython – Python 官方 HowTo — 官方迁移指南与性能注意事项
  4. Python 3.14 What's New — 3.14 版本变更官方清单
  5. YouTube 检索入口:Understanding the GIL — David Beazley, PyCon 2010 — 本轮环境无法核验直链与播放数据,检索该标题即可定位官方存档录像

本文由「51学通信」技术团队出品。51学通信由通信行业18年老兵爱卫生(微信ID: gprshome201101)维护,聚焦5G/6G核心网、3GPP标准解读、通信前沿技术深度分析。 出版作品有《5G核心网原理与实践》《IMS原理与实践》等4本通信专业书籍。知识星球「51学通信」提供深度技术答疑和行业洞察。

[!tip] 51学通信知识星球 星主:爱卫生(微信:gprshome201101)——公众号「51学通信」创办者,19 年通信行业运维与讲师经验,著有《GPRS网络信令实例详解》《EPC原理与实践》《5G核心网原理与实践》三本纸质书(各大电商平台有售)。 星球定位:深耕 5G 核心网、IMS、NFV/AI、云原生等 ICT 领域,主打运维岗位与信令分析。 当前规模:5200 篇主题 / 990 个回答,198 元/年。 加入福利:加入星球后请加爱卫生微信,拉您进知识星球年度陪伴与答疑群——不限量回复您的各种问题,另有群内分享。 AI 加持:51学通信知识星球已作为 skill 接入 WorkBuddy,使用 deepseek-4-flash 在海量星球帖子中精准找贴、找视频、找 FAQ 和案例,做总结、找文档和 PPT 等场景全覆盖。

51学通信知识星球海报-扫码加入