Python多线程无法加速CPU密集型任务,因CPython的GIL强制单线程执行字节码;仅I/O密集型任务适用threading,CPU密集型必须用multiprocessing或ProcessPoolExecutor。

Python 的多线程在 CPU 密集型任务中基本不加速,这是由 GIL(全局解释器锁)决定的,不是写法或版本问题。
为什么 threading 无法提升 CPU 密集型任务性能
CPython 解释器为保证内存管理安全,在同一时刻只允许一个线程执行 Python 字节码。GIL 是互斥锁,不是可配置开关,也无法通过多核绕过。
- 所有纯 Python 循环、数值计算(如
sum([x**2 for x in range(10**7)]))都受GIL限制 -
threading.Thread启动再多,CPU 使用率也不会超过单核 100% - 只有当线程因 I/O(如
time.sleep()、requests.get()、文件读写)主动释放GIL时,其他线程才能运行
什么时候该用 threading,而不是 multiprocessing
适用场景非常明确:高并发 I/O 等待,且任务间无强状态共享需求。
- 同时发起 100 个 HTTP 请求 → 用
threading+requests(每个请求阻塞时自动让出GIL) - 监听多个 socket 连接并响应 →
threading比multiprocessing启动快、内存开销小 - 需要共享内存对象(如
dict、list)且不涉及复杂同步 →threading可直接引用,multiprocessing需用Manager或Queue - 避免
multiprocessing在 Windows 上反复导入主模块的问题
threading.Thread 启动后不执行?常见卡点
最常被忽略的是没调用 start(),而是误调了 run() —— 后者只是普通函数调用,仍在主线程同步执行。
立即学习“Python免费学习笔记(深入)”;
import threading import timedef worker(): time.sleep(1) print("done")
t = threading.Thread(target=worker) t.run() # ❌ 错误:同步执行,不启新线程
t.start() # ✅ 正确:异步启动线程
- 忘记
t.join()导致主线程退出,子线程被强制终止(尤其脚本末尾无等待) - 使用
lambda传参时闭包陷阱:for i in range(3): Thread(target=lambda: print(i))会全打印2,应写成lambda i=i: print(i) - 未处理异常:线程内抛出的异常不会传播到主线程,需在
target函数里捕获或重写run()
真正需要并行计算时,绕不开 multiprocessing 或 concurrent.futures.ProcessPoolExecutor
只要任务是 CPU 密集型(如图像处理、加密、科学计算),必须用进程而非线程。注意:
-
multiprocessing中的函数必须能被序列化(不能是嵌套函数、lambda、类实例方法,除非用functools.partial包装) - 进程间通信比线程慢得多,频繁传大数据(如大数组)会成为瓶颈;此时应考虑
mmap或shared_memory(Python 3.8+) -
concurrent.futures.ProcessPoolExecutor比裸用multiprocessing.Process更简洁,推荐作为默认选择
多线程的“并发”和多进程的“并行”,底层机制完全不同;混淆这两者,是绝大多数性能问题的根源。










