asyncio 基于事件循环 + 协程的单线程并发模型。async def 定义的协程函数调用后返回协程对象,不执行;交由事件循环驱动,执行到 await 时若遇到未完成异步操作,协程主动挂起(保存栈帧状态),把控制权交还事件循环去调度其他就绪协程;I/O 完成后事件循环再唤醒它从挂起点继续。本质是利用 I/O 等待时间做协作式多任务,避免线程切换开销。
协程 vs 线程:
- 调度方式:协程是协作式(只在 await 点让出),线程是抢占式(操作系统随时切换)——协程在 await 之间不用加锁,共享状态更安全。
- 开销:协程是用户态轻量对象,可轻松创建数万个;线程是内核对象,MB 级栈内存,数量受限于系统。
- 并行能力:单线程 asyncio 无法利用多核,且协程中调用阻塞式同步代码(time.sleep、requests)会卡死整个事件循环,必须用异步库(aiohttp)或
run_in_executor兜底。 - CPU 密集任务两者都不合适(GIL),应多进程。
底层演进:早期 asyncio 用 @asyncio.coroutine + yield from(生成器协程),3.5 起原生 async/await,协程对象独立于生成器实现。追问方向:事件循环如何监听 I/O 完成(select/epoll/kqueue)、Task 与 Future 的关系、asyncio.gather 并发调度、异步迭代器与异步上下文管理器。