cpu密集型任务应使用multiprocessing而非threading或asyncio,因gil使线程串行执行,multiprocessing可真正并行;io密集型首选asyncio,threading为备选;共享数据需用manager或queue,协程中须用asyncio.sleep等异步接口。

CPU 密集型任务该用 multiprocessing,不是 threading 或 asyncio
Python 的 GIL 会让所有线程在 CPU 密集场景下串行执行,实际没提速。比如做大量数值计算、图像处理、加密解密——用 threading 跑 4 个线程,耗时几乎等于单线程跑 4 次。
-
multiprocessing绕过GIL,真正并行,适合numpy纯计算、cv2图像批处理等场景 - 进程启动开销大,不适合高频创建/销毁(比如每秒几百次小任务),此时考虑
multiprocessing.Pool复用进程 -
asyncio对纯 CPU 工作完全无效,await 一个计算函数不会让出控制权,它只对 IO 等待有用
IO 密集型任务优先选 asyncio,threading 是备选
发 HTTP 请求、读写文件、数据库查询这类操作大部分时间在等网络或磁盘响应,asyncio 在等待时能切走去做别的事,单线程就能撑住几千并发。
- 用
aiohttp替代requests,用aiomysql替代pymysql,否则await一个同步库调用会阻塞整个事件循环 -
threading也能解决 IO 等待,但线程切换成本比协程高,且容易因共享状态引发竞态(比如多个线程改同一个dict) - 如果已有大量同步代码、又不想重构成
async,可用loop.run_in_executor把阻塞调用扔进线程池,但别滥用——这本质是混搭,维护成本高
共享数据时,multiprocessing 必须用 Manager 或 Queue,不能直接传变量
多进程内存隔离,父进程里的 list、dict 传给子进程后,子进程拿到的是副本,改了不影响原对象,也不影响其他子进程。
- 需要跨进程通信?用
multiprocessing.Queue或multiprocessing.Pipe,它们是线程/进程安全的 - 要共享状态(比如计数器、配置缓存)?用
multiprocessing.Manager().dict()或.Value(),但注意性能损耗:所有访问都走代理,比本地变量慢一个数量级 - 别试图用全局变量 +
fork方式“共享”,Linux 下 fork 后写时复制(copy-on-write)看似共享,一旦任一进程修改就分裂,行为不可靠
协程里别混用 time.sleep,必须用 asyncio.sleep
写了个 async def 函数,里面却调 time.sleep(1),整个事件循环就卡死 1 秒——因为这是同步阻塞调用,协程根本切不出去。
立即学习“Python免费学习笔记(深入)”;
- 所有阻塞操作都要换成异步版本:
time.sleep→asyncio.sleep,requests.get→aiohttp.ClientSession.get - 第三方库没提供异步接口?要么找替代品,要么用
loop.run_in_executor包一层,但记得限制线程池大小(默认无限创建线程,可能打爆系统) -
asyncio不是银弹:调试难度高,堆栈信息难读;错误若没被await或没加try/except,可能静默失败
真正卡住人的往往不是选哪个,而是任务类型判断错了——比如把数据库慢查询当成 CPU 密集,结果上了 multiprocessing,发现性能更差。先确认瓶颈在哪,再动代码。










