多线程为什么没有加速CPU密集任务——Python并发编程
先说结论
选择标准:CPU密集用multiprocessing(多进程绕过GIL);IO密集用asyncio或threading(GIL等IO时释放);混合任务用multiprocessing+asyncio组合。
先把这段讲顺;面试官追问时,再展开下面的原理和细节。
详细讲解
三套方案对比
| 方案 | 原理 | 适用 | GIL影响 | 大数据应用 |
|---|---|---|---|---|
| threading | 多线程共享内存 | IO密集 | 受限 | 并行调API |
| multiprocessing | 多进程独立内存 | CPU密集 | 不受限 | 并行数据校验 |
| asyncio | 单线程协程 | 高并发IO | 不受限 | 百个API并发 |
# threading——IO密集场景
import threading
def fetch_data(url):
return requests.get(url).json()
threads = [threading.Thread(target=fetch_data, args=(url,)) for url in urls]
for t in threads: t.start()
for t in threads: t.join()
# 5个API各2秒,串行10秒,5线程并行2秒
# multiprocessing——CPU密集场景
from multiprocessing import Pool
def validate_table(name):
df = pd.read_parquet(f's3://data/{name}.parquet')
return len(check_nulls(df) + check_ranges(df))
with Pool(4) as pool:
results = pool.map(validate_table, tables)
# 4张表各30秒,串行120秒,4进程35秒
# asyncio——高并发IO
import asyncio, aiohttp
async def fetch(session, url):
async with session.get(url) as r: return await r.json()
async def main():
async with aiohttp.ClientSession() as s:
tasks = [fetch(s, u) for u in urls]
return await asyncio.gather(*tasks)
# 100个API各2秒,串行200秒,asyncio约3秒
实战经验:数据校验从120秒到35秒
在某知名出海硬件品牌,4张核心表串行校验120秒。threading无效(CPU 25%),改multiprocessing后CPU 100%,35秒完成。
教训:CPU密集用threading无效是Python新手最常犯的错。看到CPU上不去就该想到GIL。
concurrent.futures——统一接口
from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor
# IO密集用ThreadPoolExecutor
with ThreadPoolExecutor(10) as e:
results = list(e.map(fetch_api, urls))
# CPU密集用ProcessPoolExecutor
with ProcessPoolExecutor(4) as e:
results = list(e.map(validate, tables))
面试高频追问
追问一:多进程之间怎么共享数据?
Pool.map()的返回值传回主进程(最简单推荐);或multiprocessing.Queue进程间队列。
追问二:asyncio和多线程能混用吗?
可以。asyncio.to_thread(func)在事件循环中调用同步函数。
追问三:Python 3.13的no-GIL?
实验性支持。成熟后threading就能真正并行CPU任务。但目前NumPy/Pandas还没适配,短期multiprocessing仍是标准方案。
总结
并发面试讲三套方案选择:threading用于IO密集,multiprocessing用于CPU密集,asyncio用于高并发IO。GIL是关键——CPU密集用threading无效。能讲出校验脚本从threading无效到multiprocessing 3.4倍提升的经历,面试官觉得你理解了GIL的实际影响。
下一篇聊Python包管理:requirements.txt和虚拟环境的正确用法。
你们Python脚本用什么并发方案?评论区聊聊~
关注「Wood聊大数据」| 9年大数据老兵,只讲大数据面试干货