You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Strand实现C++20协程中d_print的串行执行?

问题描述

现有代码

#include <boost/asio.hpp>
#include <chrono>
#include <iostream>

namespace io = boost::asio;

class test {
public:
    test(io::any_io_executor e) : exe{ std::move(e) } {}

    io::awaitable<void> delay(size_t sec) {
        io::steady_timer t{ exe };
        t.expires_after(std::chrono::seconds{ sec });
        co_await t.async_wait(io::use_awaitable);
    }

    io::awaitable<void> print_and_delay(int num) {
        std::cout << num << '\n';
        co_await delay(1);
    }

    io::awaitable<void> d_print() {
        co_await print_and_delay(1);
        co_await print_and_delay(2);
        co_await print_and_delay(3);
    }

    void start() {
        for (size_t i = 0; i != 3; ++i) {
            io::co_spawn(exe, d_print(), io::detached);
        }
    }

protected:
    io::any_io_executor exe;
};

int main() {
    io::io_context ctx;
    test t{ ctx.get_executor() };
    t.start();
    ctx.run();
    return 0;
}

当前输出

1
1
1
(delay 1 second)
2
2
2
(delay 1 second)
3
3
3
(delay 1 second)

需求说明

需要让d_print协程串行执行:同一时间仅一个d_print协程运行,期望输出如下(每行间隔1秒):

1
2
3
1
2
3
1
2
3

疑问

是否可以通过使用strand实现该需求?希望能在三个print_and_delay调用外添加类似synchronized(st) {}的机制,让后续协程等待当前运行的协程完成后再执行。


解决方案

可以用Boost.Asio的strand实现这个串行化需求。strand是一种执行器,能保证提交给它的任务按顺序执行,同一时间只有一个任务在运行,刚好符合你要的同步效果。

修改后的代码

#include <boost/asio.hpp>
#include <chrono>
#include <iostream>

namespace io = boost::asio;

class test {
public:
    test(io::any_io_executor e) : strand_{ io::make_strand(std::move(e)) } {}

    io::awaitable<void> delay(size_t sec) {
        io::steady_timer t{ strand_ };
        t.expires_after(std::chrono::seconds{ sec });
        co_await t.async_wait(io::use_awaitable);
    }

    io::awaitable<void> print_and_delay(int num) {
        std::cout << num << '\n';
        co_await delay(1);
    }

    io::awaitable<void> d_print() {
        // 绑定strand,确保后续操作串行执行
        co_await io::post(strand_, io::use_awaitable);
        co_await print_and_delay(1);
        co_await print_and_delay(2);
        co_await print_and_delay(3);
    }

    void start() {
        for (size_t i = 0; i != 3; ++i) {
            io::co_spawn(strand_, d_print(), io::detached);
        }
    }

protected:
    io::strand<io::any_io_executor> strand_;
};

int main() {
    io::io_context ctx;
    test t{ ctx.get_executor() };
    t.start();
    ctx.run();
    return 0;
}

关键修改说明

  • 替换执行器为strand:把原exe成员换成strand_,通过io::make_strand基于传入的执行器创建strand,strand会强制任务按提交顺序串行执行。
  • d_print开头绑定strand:在d_print协程开头调用co_await io::post(strand_, io::use_awaitable),这一步相当于获取strand的"执行权限",确保后续的print_and_delay调用都在strand的串行调度下完成。
  • co_spawn使用strand:启动协程时直接传入strand作为执行器,确保整个协程的调度都受strand控制,避免额外的并发调度。

这样修改后,三个d_print协程会按顺序执行:第一个完成1→2→3的输出后,第二个才开始,以此类推,完全符合期望的输出效果。

内容的提问来源于stack exchange,提问作者aleck099

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 09:28:11