我正在使用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 capture
。
main thread
设置var
的值,然后线程t
读取它。
我没有使用任何memory ordering
,例如,在将std::memory_order_release
设置为var
之后没有使用1
,在读取std::memory_order_acquire
值之前没有使用var
。更何况,我认为我做不到-因为变量var
是按值传递给lambda
的。
这样做安全吗?
如果没有,应该怎么做?
答案 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。在post
和post
调用之间调用Functor-t.join
对此进行了保证。
因此,您的代码必须是线程安全的。
您将需要一些同步方法(例如,使用post
+ mutex
)
如果lock_guard
被引用[1]传递,并且对var
进行了一些写操作[2]
是在var
和post
个调用之间执行的:
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();
。