在Python项目里,并发模型的选型直接决定了系统的吞吐能力、资源消耗和代码可维护性。面对线程、进程和协程三种主流方案,开发者往往不清楚何时该用哪一种。本文从任务特征、全局解释器锁影响和工程落地成本三个方面,给出清晰的决策思路。

一、先判断任务属于哪种类型
并发选型的第一步是区分任务是CPU密集型还是IO密集型。
- CPU密集型:如图像计算、数据压缩、复杂算法,主要消耗处理器时间。
- IO密集型:如网络请求、数据库读写、文件操作,大量时间花在等待上。
二、三种模型的核心差异
1. 多线程 threading
受GIL限制,同一时刻只有一个线程执行Python字节码,因此多线程不适合CPU密集型。但在IO等待时,线程会释放GIL,适合IO密集型且逻辑简单的场景。
from concurrent.futures import ThreadPoolExecutor
import time
def fetch(n):
time.sleep(1) # 模拟IO等待
return n * n
with ThreadPoolExecutor(max_workers=4) as ex:
results = list(ex.map(fetch, range(8)))
print(results)
2. 多进程 multiprocessing
每个进程有独立解释器和GIL,可真正并行利用多核,适合CPU密集型。缺点是进程间通信成本和内存占用较高。
from multiprocessing import Pool
def compute(x):
return x ** 3
if __name__ == '__main__':
with Pool(4) as p:
print(p.map(compute, range(10)))
3. 协程 asyncio
协程在单线程内通过事件循环切换,开销极小,特别适合高并发IO场景,如Web服务。但代码需写成异步形式,对阻塞调用敏感。
import asyncio
async def task(name):
await asyncio.sleep(1)
return name
async def main():
res = await asyncio.gather(task('a'), task('b'))
print(res)
asyncio.run(main())
三、决策参考表
| 任务特征 | 推荐模型 | 主要原因 |
|---|---|---|
| CPU密集、需多核 | 多进程 | 绕过GIL实现并行 |
| IO密集、中等并发 | 多线程 | 编写简单,复用同步库 |
| IO密集、超高并发 | 协程 | 单线程高吞吐,资源占用低 |
四、工程层面的补充建议
如果旧系统大量使用同步库,优先用线程池降低改造成本;新项目接口层并发高,可直接采用asyncio。注意在协程中不要调用阻塞函数,否则会卡住整个事件循环。
选型原则:先按任务类型定方向,再按团队熟悉度和维护成本做微调。
五、小结
Python并发模型没有绝对优劣。看清任务是算得多还是等得多,理解GIL边界,就能在线程、进程和协程之间做出稳妥选择。