Python 的 全局解释器锁(Global Interpreter Lock,简称 GIL) 是 CPython 解释器(Python 官方实现)里的一个核心机制,用一句话讲:
🔒 GIL 是一个互斥锁,用来保证任意时刻只有一个线程在执行 Python 字节码。
它是 Python 单线程安全的基础,但也是 Python 多线程性能瓶颈的根源。
⸻
一、为什么会有 GIL?
要理解 GIL 的由来,要先看 CPython 的底层:
• CPython 是用 C 语言 实现的;
• Python 对象的内存管理依赖 引用计数机制(Reference Counting);
• 每个对象都有一个 ob_refcnt 计数,表示有多少个地方引用了它;
• 当 ob_refcnt 变为 0 时,对象就会被释放。
问题来了👇
如果多个线程同时操作同一个对象,比如:
x = []
线程 A:x.append(1)
线程 B:x.append(2)
这时两个线程会同时修改 x 的引用计数。
如果不加锁,ob_refcnt 可能被改乱(竞态条件 race condition),导致内存崩溃。
为了避免这种“多线程修改内存结构”出错,CPython 设计者在最初就引入了 GIL,让任意时刻只有一个线程能执行 Python 解释器层面的操作,从而保证对象引用计数的线程安全。
✅ 简单说:GIL 是为了解决多线程下的内存安全问题,而不是为了性能。
⸻
二、GIL 的工作方式
可以想象 Python 解释器的执行过程像这样:
1. Python 启动时创建一个全局锁(_PyRuntime.ceval.gil)。
2. 任意线程在执行 Python 字节码前,必须先“拿到 GIL”。
3. 当该线程执行一段时间(或执行完一定数量的字节码)后,会释放 GIL。
4. 其他线程才能获得 GIL 继续执行。
伪代码示意:
while True:
acquire(GIL)
execute_some_bytecode()
release(GIL)
switch_thread()
这意味着:
• 所有线程会轮流获得执行权;
• 在任意时刻,只有一个线程在执行 Python 代码。
⸻
三、GIL 导致的性能问题
因为 GIL 的存在:
1️⃣ 多线程无法并行执行 CPU 计算
import threading
def cpu_task():
for _ in range(10**7):
pass # 纯计算
threads = [threading.Thread(target=cpu_task) for _ in range(4)]
for t in threads: t.start()
for t in threads: t.join()
你以为 4 个线程能加速执行,结果:
• 实际上它们串行地轮流运行;
• 4 核 CPU 只用到一个核;
• 运行时间 ≈ 单线程 × 线程数。
2️⃣ 多线程依然有上下文切换开销
• Python 解释器会定期释放 GIL(默认每 5ms 左右),让别的线程有机会执行;
• 但这种切换带来 线程调度、锁竞争 等开销。
结果是:
多线程不但没加速,还可能更慢。
⸻
四、GIL 什么时候无害甚至有益?
GIL 的坏处主要在 CPU 密集型场景。
但在 I/O 密集型任务(网络请求、文件、数据库)中,反而没那么严重:
import threading, time, requests
def io_task():
requests.get(“https://example.com”)
threads = [threading.Thread(target=io_task) for _ in range(20)]
for t in threads: t.start()
for t in threads: t.join()
• 网络 I/O 时,线程会释放 GIL;
• 其他线程可趁机执行;
• 实际上能达到“伪并行”的效果;
• 所以多线程在 I/O 场景仍然有效。
✅ 因此:
场景 是否受 GIL 影响 推荐方案
CPU 密集(加密、推理、压缩) 严重影响 多进程 multiprocessing
I/O 密集(网络、文件) 影响较小 多线程或 asyncio
⸻
五、如何绕过 GIL 限制?
1. 多进程(multiprocessing)
• 每个进程都有自己的 Python 解释器和 GIL;
• 真正的并行;
• 适合 CPU 密集任务。
from multiprocessing import Pool
with Pool(4) as p:
p.map(cpu_task, range(4))
2. C 扩展释放 GIL
• NumPy、Pandas、TensorFlow 等底层用 C/C++ 实现;
• 在执行底层计算时会手动释放 GIL;
• 因此 NumPy 的矩阵运算能并行跑。
3. 使用无 GIL 的解释器
• 例如:
• Jython(运行在 JVM 上,没有 GIL,但慢)
• IronPython(运行在 .NET 上)
• PyPy STM(早期实验性支持多线程)
• Python 3.13+:官方开始实验性引入 “No-GIL 模式”!
⸻
六、Python 3.13 的“无 GIL”进展
Python 3.13 引入了可选的 “Free Threading” 模式:
./configure --disable-gil
make
这意味着未来的 Python 版本可能:
• 去掉 GIL;
• 改为细粒度锁;
• 让真正的多线程并行成为可能。
不过目前(截至 2025 年)仍在实验阶段,很多第三方库还不兼容。
⸻
七、总结对比
特性 有 GIL(当前 CPython) 无 GIL(未来方向)
多线程并行 ❌ 否(只能伪并行) ✅ 是(多核并行)
内存安全 ✅ 简单 ⚠️ 需细粒度锁
性能(单线程) ✅ 快 ⚠️ 略有损耗
兼容性 ✅ 完全兼容 ⚠️ 需改动 C 扩展
实现复杂度 ✅ 低 🚧 高
⸻
🧠 一句话总结
GIL 是 Python 的“全局安全锁”——保证线程安全,却牺牲了多核并行。
• 对 IO 任务影响不大;
• 对 CPU 密集型任务致命;
• 可用多进程或 C 扩展绕过;
• Python 3.13 以后,有望逐步告别它。
1850

被折叠的 条评论
为什么被折叠?



