python内存管理-GIL

GIL是什么

GIL(Global Interpreter Lock,全局解释器锁)CPython 解释器(Python 的官方实现)中的一个互斥锁(mutex),它确保同一时刻只有一个线程执行 Python 字节码

🔒 互斥锁的定义:

互斥锁是一种同步原语,用于防止多个线程同时访问共享资源

GIL 正是这样一把锁:

  • 共享资源 = CPython 解释器的内部状态(如对象引用计数、内存管理器)
  • 保护方式 = 任何线程要执行 Python 代码,必须先获取 GIL

为什么要设计GIL

GIL 的核心原因:CPython 的内存管理模型

🔑 关键点:

CPython 使用“引用计数(Reference Counting)”作为主要的内存管理机制,而引用计数的增减操作必须是原子的

🔑 核心逻辑链:

Python(CPython)使用引用计数(Reference Counting)管理内存引用计数的增减必须是原子操作(否则会出错)为了保证原子性,CPython 引入了 GIL(全局互斥锁)GIL 确保同一时刻只有一个线程能修改引用计数

什么是引用计数(Reference Counting)

在 CPython 中,每个 Python 对象(如 list, str, 自定义类实例)都有一个字段叫 ob_refcnt,记录“有多少变量/容器引用了它”。

1
2
3
4
a = [1, 2, 3]      # ob_refcnt = 1
b = a # ob_refcnt = 2
c = [a, "hello"] # ob_refcnt = 3(因为 c[0] 也引用了它)
del b # ob_refcnt = 2

ob_refcnt 降到 0 时,对象立即被销毁(内存回收)。

如果没有GIL

假设两个线程同时执行 b = a

线程 A 线程 B 实际 ob_refcnt
读取 ob_refcnt = 1 读取 ob_refcnt = 1 1
计算 1 + 1 = 2 计算 1 + 1 = 2
写回 ob_refcnt = 2 写回 ob_refcnt = 2 2(但正确值应为 3!)

👉 结果:引用计数错误 → 对象可能被提前释放(程序崩溃)或内存泄漏

💥 这就是竞态条件(Race Condition):多个线程/进程并发访问共享资源时,最终结果依赖于它们的执行顺序或 timing(时序),导致程序行为不可预测、错误或崩溃。

为什么 Java/Go 不需要GIL?

语言 内存管理 是否需要全局锁
Python (CPython) 引用计数(运行时增减) ✅ 需要(GIL)
Java / Go / C# 垃圾回收(GC) ❌ 不需要
Rust 编译期所有权检查 ❌ 不需要
  • GC 语言:对象分配/回收由专用 GC 线程处理,用户线程不直接操作引用计数
  • Rust:内存安全在编译期保证,运行时无引用计数开销

什么是GC

GC(Garbage Collection,垃圾回收) 是现代编程语言中自动管理内存的核心机制。其核心思想为, 自动找出“不再使用的对象”,并回收其内存,无需程序员手动释放。

🆚 对比:手动管理 vs 自动管理

方式 代表语言 特点
手动管理 C, C++ 程序员用malloc/freenew/delete管理内存 → 容易出错(内存泄漏、野指针)
自动管理 Java, Go, C#, Python 语言运行时自动回收内存 → 安全,但有性能开销

GC是如何工作的

主流 GC(如 Java、Go)使用 “可达性分析”(Reachability Analysis)判断对象是否存活:

🌳 核心概念:根对象(Roots)

  • 全局变量
  • 当前函数的局部变量
  • CPU 寄存器中的引用

📌 判断规则:

从根对象出发,能通过引用链到达的对象 = 存活对象 无法到达的对象 = 垃圾(可回收)

python的程序并行

由于 CPython 的 GIL(全局解释器锁)存在:

  • 多线程无法在多核 CPU 上并行执行 Python 字节码(尤其是 CPU 密集型任务)
  • 但多进程可以绕过 GIL,每个进程拥有独立的解释器和内存空间,因此能真正并行,充分利用多核 CPU。
类型 是否受 GIL 限制 能否利用多核 适用场景
多线程(Threading) ✅ 受限(CPU 任务串行) ❌ CPU 任务不能✅ I/O 任务可以(因释放 GIL) 网络请求、文件读写、数据库查询等 I/O 密集型
多进程(Multiprocessing) ❌ 不受限 ✅ 能(真并行) 图像处理、模型推理、加密计算等 CPU 密集型

📌 注意:“并行”(parallelism)≠ “并发”(concurrency)
- 多线程在 Python 中实现的是 并发(交替执行),不是 并行(同时执行)(对 CPU 任务而言)。

参考资料

带大家感受一下没有GIL的CPython_哔哩哔哩_bilibili

【python】天使还是魔鬼?GIL的前世今生。一期视频全面了解GIL!_哔哩哔哩_bilibili