Python 的 GIL(全局解释器锁)限制了 同一时刻只能一个线程执行 Python 字节码

最后发布时间:2025-07-13 12:05:07 浏览量:

GIL 是 Python(CPython 实现)中的一个机制:
同一时间只有一个线程能执行 Python 字节码,即便你有多个线程
原因:CPython 为了简化内存管理(引用计数),引入了 GIL 保证线程安全。

Python 的 GIL(全局解释器锁)限制了 同一时刻只能一个线程执行 Python 字节码。
所以你即使启动 10 个线程并行执行 CPU 密集任务,它们会轮流获取 GIL,一个一个执行,看起来像是串行。

import threading

def cpu_heavy():
    count = 0
    for i in range(10**8):
        count += i
    print("done")

# 启动 4 个线程
for _ in range(4):
    threading.Thread(target=cpu_heavy).start()

你可能以为会利用多核加速,其实不会:
由于 GIL,4 个线程是串行运行的,CPU 核心使用率可能只到 100%,而不是 400%。
你会发现总耗时几乎 ≈ 单线程 × 4,这就是 GIL 的影响。

哪些操作会“释放 GIL”?
I/O 操作:如文件读写、网络请求 → 会释放 GIL → 多线程能并发
一些 C 扩展库(NumPy、Pillow)内部会释放 GIL → 并发性能好
纯 Python 的 CPU 密集计算不会释放 GIL

def io_task():
    time.sleep(2)  # 这是 I/O,释放 GIL

import time
from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor

# 模拟 CPU 密集任务:递归计算斐波那契数(慢且消耗 CPU)
def cpu_bound_task(n: int) -> int:
    if n <= 1:
        return n
    return cpu_bound_task(n - 1) + cpu_bound_task(n - 2)

N = 35  # 越大越耗 CPU,建议 35 左右做测试
TASKS = 4  # 启动 4 个并发任务

def run_with_executor(name: str, executor_class):
    print(f"\nRunning with {name}")
    start = time.time()

    with executor_class() as executor:
        futures = [executor.submit(cpu_bound_task, N) for _ in range(TASKS)]
        results = [f.result() for f in futures]

    end = time.time()
    print(f"{name} finished in {end - start:.2f} seconds")
    return results

if __name__ == "__main__":
    run_with_executor("ThreadPoolExecutor", ThreadPoolExecutor)
    run_with_executor("ProcessPoolExecutor", ProcessPoolExecutor)

快捷入口
Python 思维导图 浏览PDF 下载PDF
分享到:
标签