别再拿threading当万能钥匙了,你的程序卡成PPT,可能就因为它!
你以为的“并发”,其实是“假并发”
Python 的 GIL(全局解释器锁)是个狠角色。
你用 threading 开100个线程?不好意思,同一时间只有一个线程在跑。
尤其 CPU 密集型任务,纯属自我感动 😅。
import threading
import time
defcpu_bound():
sum(i * i for i in range(10_000_000))
start = time.time()
threads = [threading.Thread(target=cpu_bound) for _ in range(4)]
[t.start() for t in threads]
[t.join() for t in threads]
print(f"threading 耗时: {time.time() - start:.2f}s") # 实测:约8.5秒
结果?比单线程还慢——线程切换开销白加!
范式一:multiprocessing —— 真·并行,干就完了!
绕过 GIL 的唯一正道:多进程。
每个进程有独立 Python 解释器,CPU 核心全拉满 💪。
from multiprocessing import Pool
import time
defcpu_bound(x):
return sum(i * i for i in range(10_000_000))
if __name__ == "__main__":
start = time.time()
with Pool(4) as p:
p.map(cpu_bound, range(4))
print(f"multiprocessing 耗时: {time.time() - start:.2f}s") # 实测:约2.3秒!
快了近4倍!四核机器直接起飞。
但注意:进程启动开销大,别频繁创建。
范式二:concurrent.futures —— 高级封装,一行切换线程/进程
别手搓 Pool 了,concurrent.futures 更优雅。
统一接口,随时切线程或进程,调试超方便。
from concurrent.futures import ProcessPoolExecutor, ThreadPoolExecutor
import time
deftask(x):
return sum(i * i for i in range(10_000_000))
# 换成 ThreadPoolExecutor 就是线程版(但CPU任务别用!)
with ProcessPoolExecutor(max_workers=4) as executor:
start = time.time()
list(executor.map(task, range(4)))
print(f"ProcessPool 耗时: {time.time() - start:.2f}s")
代码干净,逻辑清晰,还能配合 as_completed 做异步回调。
生产环境首选,别再裸写 multiprocessing 了!
范式三:async + aiohttp —— I/O 密集型任务的终极答案
如果你的任务是爬网页、读数据库、调 API,
别用进程!太重了!async 才是王道 🚀。
import asyncio
import aiohttp
import time
asyncdeffetch(session, url):
asyncwith session.get(url) as resp:
returnawait resp.text()
asyncdefmain():
urls = ["https://httpbin.org/delay/1"] * 10
asyncwith aiohttp.ClientSession() as session:
tasks = [fetch(session, url) for url in urls]
await asyncio.gather(*tasks)
start = time.time()
asyncio.run(main())
print(f"async 耗时: {time.time() - start:.2f}s") # 约1.1秒!
10个请求几乎同时发出,而用 requests 同步版得10秒+。
I/O 等待?不存在的!事件循环把空闲时间全榨干。
别乱用!选对工具才是高手
- CPU 密集 →
multiprocessing 或 ProcessPoolExecutor - I/O 密集 →
async/await + aiohttp / aiomysql - **别再无脑
threading**,除非你只是想“看起来并发”
我见过太多人用 threading 跑科学计算,结果服务器风扇狂转,进度条纹丝不动……😅
实测对比:一张图看懂差距
数据不会骗人。选错并发模型,等于主动放弃性能。
最后一句大实话
Python 并发不是不能快,是你没用对。
别被“Python 慢”带偏节奏——用对工具,它照样飞!
下次写脚本前,先问自己:
“我这是吃 CPU,还是等网络?”
答案一出,方案自然浮现 ✨。
转发给那个还在用 threading 跑矩阵运算的同事吧 😉