【发布时间】:2020-12-15 12:53:26
【问题描述】:
我的问题是关于线程同步的。请看下面的代码:
std::vector<int> v_int;
for (size_t i = 0; i < 5; ++i) {
v_int.emplace_back(i);
}
auto f_async = std::async(std::launch::async,
[](auto v_int) mutable {
for (auto& el : v_int.get()) {
el += 10;
}
}, std::ref(v_int));
//more instructions...
f_async.get();
我的问题是 std::async 产生的新线程如何“看到”(主)线程对向量所做的修改,因为没有获取释放(互斥锁, atomic bool, atomic flag...) 来保护向量?
鉴于新线程在完全写入向量后“发生”,是否存在隐式顺序一致性?
典型的生产者/消费者应该是这样的:
std::vector<int> v_int_global;
std::atomic<bool> data_ready{ false };
void producer_int() {
for (size_t i = 0; i < 5; ++i) {
v_int_global.emplace_back(i);
}
data_ready.store(true, std::memory_order_release);
}
void transformer_int() {
while (!data_ready.load(std::memory_order_acquire));
for (auto& el : v_int_global) {
el += 10;
}
}
int main() {
std::thread t1 (producer_int);
std::thread t2 (transformer_int);
t1.join();
t2.join();
}
谢谢。
【问题讨论】:
-
en.cppreference.com/w/cpp/thread/async - 请参阅关于 synchronizes-with 的部分。虽然我没有标准可以验证它。
-
“考虑到新线程在完全写入向量后“发生”,是否存在隐式顺序一致性?” - 在您给出的示例中,是的。在这里,您启动异步任务,然后立即在返回的未来调用
.get,这有效地使整个示例同步。如果您要将填充v_int的代码移动到 对std::async的调用和对f_async.get的调用之间,您将拥有UB。
标签: c++ multithreading asynchronous language-lawyer