Python 开发手册PYTHON

CHAPTER 03并发模型 · CONCURRENCY

并发模型

Python 的并发有三条路:threading(受 GIL 限制)、multiprocessing(绕过 GIL 做 CPU 并行)、asyncio(协程做高并发 IO)。选对模型是关键。

开始阅读难度进阶约3小时
03.1

GIL 与选型

GIL(全局解释器锁)使同一进程内仅一个线程执行字节码。结论:CPU 密集用多进程,IO 密集用线程或 asyncio。

场景推荐
IO 密集(网络/磁盘)threading / asyncio
CPU 密集(计算)multiprocessing
高并发连接asyncio
03.2

threading

threading 适合 IO 并发。启动多个线程并行等待网络,主线程用 join 等待。

import threading
def fetch(url): ...
ts = [threading.Thread(target=fetch, args=(u,)) for u in urls]
[t.start() for t in ts]; [t.join() for t in ts]
03.3

锁与队列

共享可变状态用 Lock 保护;线程间通信用 queue.Queue(线程安全),优于手动加锁。

import queue
q = queue.Queue()
q.put(item); item = q.get()      # 线程安全
03.4

multiprocessing

多进程绕过 GIL,真正并行利用多核;Pool 简化并行映射,代价是进程间通信开销。

from multiprocessing import Pool
with Pool(4) as p:
    results = p.map(heavy_compute, data)
03.5

asyncio 基础

asyncio 用单线程事件循环调度协程,在 IO 等待时切换,支撑海量并发连接。

import asyncio
async def main():
    print("start")
    await asyncio.sleep(1)
    print("done")
asyncio.run(main())
03.6

async/await 与并发

async 定义协程,await 挂起;asyncio.gather 并发运行多个协程。

async def fetch(u): ...
async def main():
    results = await asyncio.gather(*(fetch(u) for u in urls))
03.7

并发原语

asyncio 提供 Semaphore(限流)、Lock、Queue 等;注意阻塞调用(如 time.sleep)会卡住事件循环,要用 await asyncio.sleep。

别在协程里阻塞

在 asyncio 中调用同步阻塞函数会阻塞整个循环。用 run_in_executor 把阻塞任务丢到线程池。

03.8

常见陷阱

为什么多线程没让计算更快?

CPU 密集任务受 GIL 限制,多线程只是并发非并行。改用 multiprocessing 或释放 GIL 的 C 扩展(如 NumPy)。

asyncio 里用了 requests 卡住?

requests 是阻塞同步库,会卡事件循环。异步场景用 aiohttp/httpx(async),或对同步调用用 run_in_executor。

03.9

实战练习

延伸资源