在 lambda 的捕获中传递参数以提升 asio post/dispatch 线程安全吗?

Does passing parameters in lambda's capture to boost asio post/dispatch thread safe?

我正在使用 lambda's capture 以便将参数传递给 boost::asio::io_context::post 回调。
它是线程安全的吗?

代码

#include <iostream>
#include "boost/asio.hpp"
#include <thread>

int main() {
    boost::asio::io_service io_service;
    boost::asio::io_service::work work(io_service);

    std::thread t([&](){
        io_service.run();
    });

    auto var = 1;
    io_service.post([&io_service, var]() {
        std::cout << "v: " << var << std::endl;
        io_service.stop();
    });

    t.join();

    return 0;
}

如您所见,我在 lambda's capture 中传递了 varmain thread 设置 var 的值,线程 t 读取它。
我没有使用任何 memory ordering,例如,将 var 设置为 1 之后的 std::memory_order_release,以及读取 var 值之前的 std::memory_order_acquire。更重要的是,我不认为我可以 - 因为变量 var 按值传递给 lambda.

这样做安全吗?
如果不行,应该怎么做?

它是线程安全的。

闭包对象在 var 创建并初始化后由主线程创建(复制 var 值)。 接下来,闭包对象作为参数传递给 post 方法,该方法将此函数对象和 returns 立即排队,而不调用仿函数。 Functor 在 postt.join 调用之间被调用 - post 保证它。 所以你的代码必须是线程安全的。

您需要一些同步方法(例如,使用 mutex+lock_guard) 如果 var 是通过引用 [1] 和 var [2] 上的一些写入操作传递的 在 postt.join 调用之间执行:

auto var = 1;
io_service.post([&io_service, &var]() { // [1] takes by reference
    std::cout << "v: " << var << std::endl; // lock mutex for printing
    io_service.stop();
});
var = 10; // [2] , lock mutex for writing
// synchronization must be added because between post and t.join calls,
// reading and writing operations are executed
t.join();

在这种情况下,您必须保护 var