协程更适用于I/O密集或高并发场景;线程由操作系统调度、开销大,协程用户态调度、栈小切换快,10万连接用线程内存超100GB而协程可行。

协程和线程是C++中两种不同层级的并发抽象:线程由操作系统调度,对应真实CPU执行单元;协程由用户态代码控制调度,本质是可挂起恢复的函数。选线程还是协程,关键看任务类型——CPU密集用线程,I/O密集或高并发场景协程更轻量高效。
调度机制与资源开销差异明显
线程由内核调度,创建销毁需系统调用,上下文切换涉及寄存器、内存映射等,单线程栈默认1MB左右;协程在用户态协作式调度(C++20 `co_await` + 自定义 awaiter),栈可按需分配(如几KB),切换只需保存/恢复少量寄存器和栈指针,开销低两个数量级以上。
- 10万并发连接用线程:内存占用超100GB,几乎不可行
适用场景有明确分界
线程适合需要真正并行执行的任务,比如图像处理、矩阵运算、物理模拟等CPU密集型工作;协程适合大量等待I/O(网络请求、数据库查询、文件读写)的场景,尤其是服务端需同时处理数万客户端连接时。
- Web服务器处理HTTP请求:每个请求用协程封装,等待socket读写时不阻塞其他协程
- 实时音视频编码:必须利用多核并行,应使用线程池+OpenMP或std::thread
- 混合场景(如游戏服务器):用线程池处理逻辑计算,协程处理网络收发
C++20协程不是“开箱即用”的线程替代品
C++20只提供协程语法(co_await、co_yield、co_return)和底层原语,不带运行时调度器。你得自己实现或选用第三方库(如Boost.Asio 1.70+、cppcoro、libunifex)来管理协程生命周期和唤醒逻辑。而线程直接用std::thread或std::jthread即可启动。
立即学习“C++免费学习笔记(深入)”;
- 新手建议从Boost.Asio的
awaitable入手,它封装了IO调度,API较友好 - 避免手写调度器,除非明确需要极致定制(如嵌入式低延迟场景)
- 协程函数返回类型必须满足promise_type协议,编译器据此生成状态机,不是所有函数都能加
co_await
错误混用会导致严重问题
在协程中直接调用阻塞API(如sleep(1)、fread、未设非阻塞的recv)会卡住整个线程上的所有协程;反过来,在线程中滥用协程(比如在std::thread里启动大量未绑定调度器的协程)会导致协程永远不被唤醒。
- 网络I/O务必用异步接口(如
async_read)配合co_await - CPU密集操作别放在协程里跑太久,应切片或交还调度器(如
co_await std::experimental::suspend_always{}) - 跨线程访问协程对象需注意生命周期——协程可能在另一线程恢复,确保捕获的变量仍有效











