一句话定义:协程(Coroutine)是可以中途暂停、把控制权交出去、之后再从暂停处接着跑的函数。
普通函数必须跑到 return 才罢休;协程则可以在某一点主动说“我这会儿没事干”,让出控制权,等条件满足再回来。负责调度它们的角色叫事件循环(Event Loop)。
打个比方:线程模型是每来一桌客人就雇一个服务员,人多时工资和工位都是成本,换手还要交接;协程模型则是一个服务员管十桌——A 桌等水开,他先去给 B 桌点单,谁准备好了就回来处理谁。人没停,停的只是某一桌的进度。协程的本质就是把“等待”从“占着人不放”换成“记个记号先走开”。
async/await 在等什么:几乎总是 I/O,比如网络回包、磁盘读写、数据库查询。await 一个请求时,运行时做的是“登记:回包到了叫我”,然后把 CPU 交还给事件循环,去跑别的协程。它不消耗 CPU、不占用操作系统线程,等的不是时间,而是事件。所以有个困惑就说得通了:在协程里写 time.sleep() 或跑一个大循环,没人会来救场,因为那不是在等,是在占。
| 线程(Thread) | 协程(Coroutine) | |
|---|---|---|
| 谁调度 | 操作系统 | 程序自己(事件循环) |
| 切换成本 | 高,要进内核、换栈 | 极低,函数跳转级别 |
| 数量级 | 几百到几千 | 几万到几十万 |
| 擅长 | 并行计算、阻塞调用 | 高并发 I/O 等待 |
为什么跑不了 CPU 密集任务:协程的让出是自愿的,只有执行到 await 才交班,没有谁能中途把它踢下去;而事件循环通常只跑在一个线程上。于是一个协程闷头算十分钟,其他所有协程就干等十分钟,轻量的好处全没了,还多背一层复杂度。CPU 密集的活该给多进程、线程池,或干脆下沉到原生代码。
对从业者的意义:AI 应用里大部分时间花在“等”上,比如等模型返回、等向量库检索、等上游接口。这类服务用异步框架,能用很小的资源扛住很高并发。记住边界:I/O 密集交给协程,CPU 密集交给进程;拿不准就问一句“这段代码是在等,还是在算”。具体能力与限制以官方文档为准。
