发布于2026-07-08 阅读(0)
扫一扫,手机访问
Python多线程在CPU密集型任务中变慢,这不是写错了代码,而是CPython解释器在背后强制你“排队计算”——GIL让所有线程抢同一把锁,谁拿到谁算,其余只能干等着。这不是bug,而是设计上做的取舍。

原因其实很实在:线程启动、切换、争抢GIL本身就要消耗CPU时间片。而纯计算任务又不触发GIL释放——它不像requests.get()或open()那样会主动让出锁——结果多个线程在单核上反复做上下文切换,实际执行仍然是串行的。
threading跑计算任务反而更耗时?GIL才有可能轮转一次,但轮转开销远大于收益fibonacci()、sum([i**2 for i in range(10**7)])这类场景中经常出现concurrent.futures.ThreadPoolExecutor包装再多层,也绕不开这个底层限制multiprocessing真能解决问题吗?能,但代价很明确:进程间不共享内存,每次传参或取结果都要走pickle序列化,数据越大越拖慢速度;启动新进程本身也有毫秒级开销。
Process——用Pool或ProcessPoolExecutor复用进程会更划算if __name__ == '__main__':,否则会报RuntimeError: An attempt has been made to start a new processmultiprocessing更轻量的替代方案有哪些?不是所有计算都值得上多进程。先看看能不能“不动线程模型,只换执行体”:
NumPy/SciPy数组运算:底层由C/Fortran实现,会自动释放GIL,单线程就能吃满多核concurrent.futures.ProcessPoolExecutor + functools.partial:比裸multiprocessing更容易管理,支持超时和回调ctypes封装C函数:在C代码段手动调用PyThreadState_Release和PyThreadState_Swap释放GIL,适合已知的热点函数真正容易被忽略的点:GIL不是“锁住整个程序”,而是“锁住Python字节码执行”。只要计算逻辑能下沉到不经过解释器的层面(比如向量化、C扩展、甚至subprocess.run(['rust-code'])),就自然绕开了它——优化方向不在于“怎么开更多线程”,而在于“让哪部分代码彻底不走Python解释路径”。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8