多进程适合CPU密集型任务,因GIL限制多线程无法提升Python的CPU性能;I/O密集型可用threading或asyncio;混合场景应拆分处理,避免GIL与阻塞互相拖累。

多进程适合 CPU 密集型任务,多线程在 Python 里几乎不提升 CPU 性能
这是由 GIL(全局解释器锁)决定的:CPython 中同一时刻只有一个线程能执行 Python 字节码。所以即使开了 10 个 threading.Thread 做数值计算,实际仍是串行执行,还多了线程切换开销。
常见错误现象:time.time() 测出来多线程比单线程还慢;top 或任务管理器显示 CPU 占用率始终卡在 100%(单核),而不是接近 N×100%。
适用场景:
- CPU 密集型(如科学计算、图像处理、加密解密)→ 用
multiprocessing - I/O 密集型(如 HTTP 请求、文件读写、数据库查询)→
threading或asyncio都可,前者更简单
multiprocessing.Pool 比手动创建 Process 更省心也更高效
直接用 Process 启动几十个子进程容易失控:进程生命周期难管理、结果收集要自己搞共享内存或队列、异常传播困难。而 Pool 封装了进程复用、任务分发、结果聚合和错误回传。
立即学习“Python免费学习笔记(深入)”;
实操建议:
BJXSHOP购物管理系统是一个功能完善、展示信息丰富的电子商店销售平台;针对企业与个人的网上销售系统;开放式远程商店管理;完善的订单管理、销售统计、结算系统;强力搜索引擎支持;提供网上多种在线支付方式解决方案;强大的技术应用能力和网络安全系统 BJXSHOP网上购物系统 - 书店版,它具备其他通用购物系统不同的功能,有针对图书销售而进行开发的一个电子商店销售平台,如图书ISBN,图书目录
- 用
pool.map(func, iterable)替代循环调用Process(target=func, args=(x,)) - 注意
iterable会被序列化(pickle),不能传 lambda、嵌套函数、带绑定方法的对象 - 默认进程数是
os.cpu_count(),CPU 密集任务别盲目设更大值,反而因调度开销拖慢整体
线程池 concurrent.futures.ThreadPoolExecutor 是 I/O 任务的首选
相比原始 threading 模块,它自动管理线程生命周期、支持 as_completed 和超时控制,且 API 与 ProcessPoolExecutor 一致,方便后续替换为多进程。
典型误用:
- 用
ThreadPoolExecutor跑纯计算(比如sum([i**2 for i in range(10**6)]))→ 白忙活,GIL 锁死 - 忘记调用
shutdown(wait=True)或没用with上下文 → 程序可能提前退出,任务被丢弃 - 提交太多任务到线程池(比如 10000 个 HTTP 请求)→ 不是线程越多越快,通常 10–50 个线程就足够压满网络带宽
混合场景:I/O + CPU 拆开做,别让 GIL 和阻塞互相拖累
比如“下载图片 → 缩略图处理”这种组合任务,不能全扔给线程(缩略图卡 GIL),也不能全扔给进程(下载部分启动开销大、上下文切换重)。
推荐做法:
- 用
ThreadPoolExecutor下载一批图片(I/O 并发) - 把下载完的本地路径列表交给
ProcessPoolExecutor批量做缩略图(CPU 并发) - 避免跨进程传递原始图片二进制数据,改传文件路径——减少 pickle 开销和内存拷贝
最容易被忽略的是:子进程无法继承主线程的 TLS(线程局部存储)、数据库连接、日志 handler 等资源,初始化必须放在子进程内部,不能靠父进程传入。










