轻松下单
用std :: memory_order_relaxed标记的原子操作不是同步操作;只有线程之间共享每个原子对象的修改顺序。不同的对象相对于其他线程在它们之间没有排序;操作可以看不到。
示例 - 放宽订购
#include <atomic>
#include <thread>
#include <assert.h>
std::atomic<int> x{ 0 };
std::atomic<bool> x_is_set{ false };
std::atomic<int> counter{ 0 };
void f1()
{
x.store(5, std::memory_order_relaxed); // A
x_is_set.store(true, std::memory_order_relaxed); // B
}
void f2()
{
while (!x_is_set.load(std::memory_order_relaxed)); // C
if (x.load(std::memory_order_relaxed) == 5) // D
++counter; // E
}
int main()
{
std::thread t1{ f1 };
std::thread t2{ f2 };
t1.join();
t2.join();
assert(counter.load() == 1); // F
}
线程 t1 与线程 t2 之间没有排序限制。因此,在商店完成 A 之前,可以通过 t 查看 B 中完成的商店;在这种情况下,main()中的断言 F 将触发。
此问题的明显解决方案是使 B 中的商店具有std::memory_order_release
并且 C 中的加载具有std::memory_order_acquire
用于同步目的。 F 中的断言似乎永远不会发生。
问题
但是,由于 A 和 B 之间没有发生 - 之前的关系(我错了吗?),不能编译器/ optimizer / CPU重新组织函数f1()
中的指令,以便 B 之前 这会导致函数f2()
中的 C 评估为true
,但 D 将为false
;断言可以解雇。
是否存在阻止该问题发生的任何事情?
答案 0 :(得分:4)
因为A和B之间没有发生之前的关系
错误。 [intro.multithread] / P14:
评估A 在评估B之前发生,如果:
- A在B之前排序,或
- 线程发生在B之前。