Boost::Asio与C++20协程的关系及异步技术选型疑问
学习背景
- 最初接触Boost::Asio时直接啃官方文档和示例代码,整体理解门槛很高,后来发现核心卡点是Asio的编程模型和协程的执行逻辑高度相似。
- 为了打通理解链路,决定先系统学习协程,先从CppCon历年协程主题演讲看起:2014年的一场协程主题演讲里给出过如下示例代码,由于编写时间远早于C20协程标准定稿,语法和正式的C20标准协程并不一致:
auto conn = await Tcp::connect.Read("127.0.0.1", 1337)
- 能看出来这种早期协程的写法和Boost.Asio的设计目标非常契合;另外Boost.Asio官方文档的示例章节里,有一个混合使用Boost.Asio和C++20协程实现的节流代理示例,目前还没完全捋清楚这个示例的执行逻辑,因此整理了三个核心技术问题。
问题解答
1. Boost.Asio与协程的具体关系是什么?协程是否会替代Boost.Asio的部分能力?
两者不存在替代关系,本质是异步技术栈上分层互补的两类组件:
- Boost.Asio的核心是跨平台异步I/O与执行框架,底层封装了各个操作系统原生的异步IO机制(Linux下的epoll、Windows下的IOCP、macOS下的kqueue等),对外提供统一的事件循环、IO对象抽象、任务调度、定时器、串行化执行保证(strand)等基础能力。Asio从设计之初就没有绑定某一种异步编程范式,在C++20协程标准落地之前,它已经支持回调、栈式协程(boost::coroutine、asio::spawn模式)、无栈协程、Future等多种异步写法。
- C++20协程是语言层面提供的控制流抽象,本身不内置任何IO调度、任务执行的能力,只解决“异步代码写起来不用嵌套回调、逻辑和同步代码一致”的语法体验问题。协程里的
co_await等待、挂起后的恢复执行,都需要Asio这类执行框架提供实际的调度支撑。 - 现在Asio对C++20协程的适配,本质是在原有框架能力上加了一层更易用的编程接口:你可以用
co_await的线性写法写异步逻辑,不用再搭回调金字塔,但底层跑的事件循环、IO收发、线程调度逻辑,还是Asio本身的成熟实现。 - 不存在协程替代Asio能力的情况,反而是协程的普及会放大Asio这类成熟框架的价值——毕竟没人会为了用协程,从零开始手写跨平台的IO多路复用、事件循环逻辑。只有当你的场景完全不需要复杂调度、也不涉及IO,只是用协程写个简单的生成器时,才不需要引入Asio,但这是场景本身不需要Asio的能力,和协程替代无关。
2. 如果开发场景不涉及网络编程,是否仍有必要使用Boost.Asio?
要不要用完全看场景需求,Asio从一开始就不是专门为网络编程设计的库,它的核心能力覆盖所有事件驱动、异步执行的场景,非网络场景下这些情况用Asio能省大量跨平台适配和底层踩坑的成本:
- 需要跨平台的异步定时器:Asio提供的
steady_timer、system_timer做了全平台适配,不用自己在Linux下写timerfd、Windows下写WaitableTimer的兼容逻辑,还能和其他异步逻辑无缝衔接。 - 需要稳定的线程池、任务调度能力:Asio的
io_context、thread_pool是经过大量生产环境验证的执行器实现,支持任务投递、strand串行化保证(不用自己加锁就能解决多线程下共享资源的并发访问问题),比自己手搓的线程池稳定性高很多。 - 需要处理非网络类IO:Asio内置了串口(
serial_port)、系统信号(signal_set)、管道等IO对象的抽象,跨平台做串口读写、信号捕获比直接调系统API方便很多。 - 需要做异步流程编排:不管是延迟执行任务、多异步步骤串行、多线程无锁任务队列,Asio已经把很多高频踩坑的底层逻辑封装好了。
反过来如果你的程序是纯同步逻辑,没有任何异步执行、事件驱动的需求,所有操作都是按顺序阻塞执行的,那完全没必要引入Asio,平白增加依赖复杂度。
3. std::async以及senders/receivers提案在整个C++异步技术体系中分别处于什么定位?
这几个技术组件分别在异步技术栈的不同层级,定位差异很大:
std::async是C++标准库早期提供的轻量高层异步任务接口,定位非常单一:给开发者一个极简的方式把单个函数扔到后台执行,返回std::future用来拿执行结果。它没有自定义调度器的概念,不支持IO等待,也没有异步流程编排能力,甚至连执行策略的控制度都很低(多数标准库实现要么默认起新线程,要么用非常简单的内置线程池),只适合“把单个耗时计算任务扔到后台不阻塞主线程”的极简单场景,复杂异步场景下基本不够用——你没法用它串联多个异步步骤,没法绑定到自定义事件循环,也没法对接异步IO的等待逻辑。- Senders/Receivers(也就是C23正式纳入标准的
std::execution相关内容)是通用异步执行模型的标准抽象规范,本质是定义了一套统一的异步操作、调度器、异步流程组合的接口标准,解决的是之前C异步生态里各个框架(Asio、PPL、各类自研协程库)接口不统一、组件无法互相组合的问题。它本身不是具体的IO实现,也不是开箱即用的线程池/事件循环,更像一套跨框架的“通用协议”:只要你的执行器、异步操作符合Senders/Receivers规范,就可以和其他合规组件自由组合,不管底层是Asio的事件循环、自定义线程池还是其他异构计算调度器,上层的组合逻辑都不需要修改。
内容的提问来源于stack exchange,提问作者Mark Wallace
相关产品推荐
相关产品推荐

