C++11 原子。可见性和 thread.join()/停止线程的正确方法

标签 c++ multithreading memory-model stdatomic memory-visibility

对于哪些(如果有的话?)STORE_ORDERLOAD_ORDER C++11 保证此代码在有限时间内运行?

std::atomic<bool> a{false};
std::thread t{[&]{
  while(!a.load(LOAD_ORDER));
}};
a.store(true, STORE_ORDER);
t.join();

我看到两个问题:

内存顺序

在我看来,使用 releaseaquire,编译器和 cpu 可以重新排序我的 join(假设它的行为类似于load) 在 store 之前,这当然会破坏它。

即使使用 memory_order_seq_cst,我也不确定这样的重新排序是否被禁止,因为我不知道 join() 是否真的进行了任何加载或存储。

可见度

如果我明白this question about memory_order_relaxed正确地,不能保证具有 memory_order_relaxed 的存储在有限时间内对其他线程可见。其他订单有这样的保证吗?

我知道 std::atomic 是关于原子性和内存排序的,而不是关于可见性的。但我不知道 c++11 中的任何其他工具可以帮助我。我是否需要使用特定于平台的工具来获得正确性保证?如果需要,使用哪个工具?


更进一步——如果我有有限性,那么最好也有一些关于速度的 promise 。我不认为 C++ 标准做出任何这样的 promise 。但是是否有任何编译器或特定于 x86 的方法来保证存储将很快对其他线程可见?


总结:我正在寻找一种方法来快速停止实际保证具有此属性的工作线程。理想情况下,这将与平台无关。但如果我们不能拥有它,它是否至少存在于 x86 上?

最佳答案

经过更多的搜索,我发现了一个与我的可见性部分相同的问题,它得到了a clear answer。 :确实没有这样的保证——只有要求“实现应该使原子存储在合理的时间内对原子加载可见”。该标准没有定义“应该”的含义,但我会假设正常的含义,因此这将是非约束性的。它也不太清楚“合理”是什么意思,但我认为它明确排除了“无限”。

这并没有完全回答有关内存排序的问题。但是,如果存储在 join() 之后排序,这可能会永远阻塞,则存储将永远不会对其他线程可见——这将不是“合理的时间量”。

因此,虽然标准不要求问题中的代码有效,但它至少表明它应该有效。作为奖励,它实际上说它不应该只是有限的时间,而且还应该有点快(或者说,合理)。

这就剩下我关于平台特定解决方案的部分问题了:是否有一种特定于 x86 的方法来编写所请求的算法,从而保证它实际上是正确的?

关于C++11 原子。可见性和 thread.join()/停止线程的正确方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54712549/

相关文章:

c++ - 在一个线程中完成的操作对另一个线程可见,而无需显式同步

python - 从Python子线程接收数据的简单方法

java - 为什么我们不能应用 JLS 中包含的保证?

c++ - 注入(inject) C++ DLL

c++ - 在 C++ 中读取 .docx

c# - 单体机器人 : Intermittent failure when reading a large json string from web service

c++ - memory_order_seq_cst 栅栏什么时候有用?

c++ - 非原子对象在所有线程中是否具有相同的修改顺序? (在没有数据竞争的情况下)

c++ - 解析为 x3::variant 时出现编译器错误

c++ - 如何在Qt无框窗口中实现QSizeGrip?