为什么你不能拿 GIL 尬黑 (C)Python
ProgramRipper
2026年04月01日 00:24

叠甲:本文旨在澄清一些关于 GIL 和 CPython 的误解。 如果你被某人发送了这篇文章,说明你可能其实并没有对 Python 有非常深入的了解。 这不是你的错,即使是作者(使用 Python 长达 10 年)也非常依赖搜索引擎、LLM 以及实验以确认本文的内容。 但是如果你只是想尬黑 Python 的性能就是不如其他语言,那你现在可以关闭这篇文章,并承认你就是想尬黑了。

名词解析 (1):CPython 是什么?我们不是在聊 Python 吗?

CPython 是 Python(语言)的一个实现,使用 C 编写。 它是最常用的 Python 实现,也是 Python 的参考实现。 除了 CPython 之外,还有其他 Python 实现,如 PyPy(自举实现)、GraalPy(基于 GraalVM 的实现)、IronPython(基于 .NET 的实现)等。CPython 也有各种分支,如 nogil(Meta 工程师 Sam Gross 的没有 GIL 的实验性实现)和 Cinder(Meta 内部生产环境使用的 Python 实现)等。

为什么要强调是 CPython?

因为 GIL 不会影响 Python 语言上的语义,它只是 CPython 的实现细节。就像:

  • C++ 的多线程 (std::thread) 的实现在 *nix 上是 POSIX 线程,在 Windows 上是 Win32 线程。

  • JavaScript 的多线程的实现在浏览器上是 Web Worker,在 Node.js 上是 Worker threads。

大多数情况下,GIL 影响的其实是 CPython 的 C 扩展的编写。 而前面提及的各种 Python 实现中,GraalPy(使用 JVM 线程模型)、IronPython(使用 CLR 线程模型)和 nogil 都没有 GIL。 即使是有 GIL 的实现,它们的 GIL 也与 CPython 的 GIL 实现完全不同。 所以为了准确地讨论 GIL,我们必须明确讨论的是 CPython 这一实现。

名词解析 (2):GIL 是什么?

GIL (Global Interpreter Lock,全局解释器锁) 是一个互斥锁,确保一个 CPython 解释器同一时间只有一个线程可以执行 Python 字节码,主要目的是保护 CPython 的解释器状态、数据结构完整性和简化 C 扩展使用 CPython API 时的内存管理。

名词解析 (3):线程是什么?

你可能会想:这人哪来的资格教我操作系统概念? 抱歉,我无意在此科普操作系统的线程是什么。 但是本文提及的“线程”,是指 CPython 中的 threading.Thread。 事实上,你对 GIL 的偏见,很有可能出自于对 threading.Thread 的误解:

threading.Thread 是内核线程,不是用户线程

也就是说,threading.Thread 是由操作系统调度的线程,而不是由 CPython 解释器调度的线程。 这与:

  • C++ 的 std::thread

  • Java 的 Thread (Platform Thread)

  • .NET (C#) 的 System.Threading.Thread

  • Node.js (JavaScript) 的 worker_threads.Worker (Worker thread)

  • Ruby MRI 的 Thread

是一致的,而与:

  • Go 的 go (Goroutine)

  • Java 的 Thread.ofVirtual (Virtual Thread)

  • Ruby MRI 的 Fiber

是不一致的。

多个 threading.Thread 共享同一个解释器

一个 CPython 解释器可以创建多个 threading.Thread,这些线程共享同一个解释器实例。 这与:

  • Java 的 Platform Thread

  • .NET 的 System.Threading.Thread

  • Ruby MRI 的 Thread

是一致的,而与:

  • Node.js 的 Worker thread

  • 浏览器 (JavaScript) 的 Web Worker

  • BEAM VM (Erlang/Elixir) 的 Erlang process

是不一致的。

CPython 是一个多线程的解释器

取上述两个 threading.Thread 的特性的交集,我们可以得出结论:CPython 是一个多线程的解释器,支持在多个线程中,被外部调度的情况下,共享同一个解释器实例。 这也是为什么 CPython 需要 GIL,因为在这种情况下就是需要一个锁来保护各种线程不安全的操作。

很多解释器实际上不是多线程的解释器:

  • V8 (JavaScript): 每个 Node.js 的 Worker thread 都有一个独立的 V8 Isolate

  • Web worker: 每个 Web Worker 都有一个独立的 JavaScript 执行上下文

  • Lua: 宿主程序决定如何组织,但是每个 Lua 协程通常使用独立的 lua_State

  • BEAM VM: 每个 Erlang process 都有一个独立内存空间

它们的线程并行,对应的 CPython 实现是 concurrent.interpreters.Interpreter (Sub-interpreter),而非 threading.Thread。 而以下这些解释器和 CPython 一样,是多线程的解释器:

  • JVM

  • Ruby MRI: 你猜猜它有什么?GVL (Global VM Lock),和 GIL 一样的东西

  • GHC (Haskell)

现在你可以想象出一个没有 GIL 的解释器可能存在的难题了:

  • 细粒度锁:每个解释器状态、数据结构、内存管理都需要细粒度的锁保证原子性

  • 性能:大量临界区的进出和锁的竞争,给单线程应用带来严重的性能损失

所以 GIL 的存在是有其合理性的,只是一个工程上的权衡结果,并且并不意味着 CPython 缺乏并行能力(多解释器和多进程)。

你可能不需要多线程

很多情况下使用多线程,其实需要的只是并发 (concurrency),而非并行 (parallelism)。 而 CPython 的 GIL 不影响线程的并发能力,更何况 Python 还有 asyncio、greenlet 等协程可以提供更加轻量高效的并发。 即使真的需要并行,那更可能是 CPU 密集型的任务,而非 I/O 密集型的任务。 而 CPU 密集型任务在 Python 生态中往往是 C 扩展执行的,C 扩展可以手动释放 GIL 来实现不涉及 CPython 解释器的并行。 即使真的需要 Python 层面上的并行,也可以使用多解释器或者多进程来实现。 总之,GIL 给 Python 带来的影响,往往是被夸大了的。

现状

说了这么多,其实 GIL 即将会是一段历史了。

GIL 曾经还是“进程全局锁”

GIL 曾经不只是全局解释器锁,还是“进程全局锁”,即一个进程内的所有解释器实例都共享同一个 GIL。 而在 Python 3.12 (2023 年 10 月 2 日发布) 中,PEP 684 (A Per-Interpreter GIL) 将 GIL 改为了 Per-Interpreter GIL,即每个解释器实例有自己的独立 GIL, 这让 CPython 有了多解释器的并行能力。

GIL 曾经还是 CPython 的必须部分

自从 Sam Gross 的 nogil 证明了可行性后,以他为首的开发者们(其中许多人受雇于 Meta)积极投入资源到创造一个没有 GIL 的 CPython 中:

  • Python 3.13 (2024 年 10 月 7 日发布) 中,PEP 703 (Making the Global Interpreter Lock Optional in CPython) 将 GIL 变成了可选项,并且发布了实验性的自由线程的 CPython (Free-threaded CPython) 构建。

  • Python 3.14 (2025 年 10 月 7 日发布) 中,PEP 779 (Criteria for supported status for free-threaded Python) 让自由线程的 CPython 获得官方支持,而非实验性的构建。

  • Python 3.15 (预计 2026 年 10 月发布) 中,PEP 803 (“abi3t”: Stable ABI for Free-Threaded Builds) 将会让自由线程的 CPython 拥有稳定的 C API (Stable ABI),使得 C 扩展只需一次编译即可支持未来所有版本的自由线程的 CPython。

  • 未来的某个版本中,自由线程的 CPython 将会成为默认构建,而不再提供有 GIL 的构建。


希望以上的内容可以让你理解,为什么你在提到 GIL 的时候,往往会被认为是在“尬黑” CPython。 因为虽然 GIL 影响很大,但没有那么大,大到所有 Python 开发者都需要在意它。 而如果你很在意它,往往说明你可能不是一个 Python 开发者,自然在 Python 开发者眼中,你对 Python 的评价就不太可能是客观的了。