在lambda的捕获中传递参数以增强asio发布/调度线程是否安全?

时间:2018-11-12 19:33:57

标签: multithreading c++11 boost synchronization boost-asio

我正在使用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;
}

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

这样做安全吗?
如果没有,应该怎么做?

1 个答案:

答案 0 :(得分:1)

这是线程安全的。

创建和初始化#[macro_use] extern crate serde_derive; extern crate serde; #[derive(Deserialize, Debug)] struct Quux { foo: Foo, name: String, } #[derive(Deserialize, Debug)] #[serde(rename_all = "lowercase")] enum Foo { Bar, Baz, } fn main() { let j = r#" { "foo": "bar", "name": "some name" } "#; println!("{:#?}", serde_json::from_str::<Quux>(j).unwrap()); } 后,关闭对象由主线程创建(复制var值)。 接下来,将闭包对象作为参数传递给var方法,该方法对该函数对象进行排队并立即返回而无需调用functor。在postpost调用之间调用Functor-t.join对此进行了保证。 因此,您的代码必须是线程安全的。

您将需要一些同步方法(例如,使用post + mutex) 如果lock_guard被引用[1]传递,并且对var进行了一些写操作[2] 是在varpost个调用之间执行的:

t.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();