我有以下 C++ 2011 代码:
std::atomic<bool> x, y;
std::atomic<int> z;
void f() {
x.store(true, std::memory_order_relaxed);
std::atomic_thread_fence(std::memory_order_release);
y.store(true, std::memory_order_relaxed);
}
void g() {
while (!y.load(std::memory_order_relaxed)) {}
std::atomic_thread_fence(std::memory_order_acquire);
if (x.load(std::memory_order_relaxed)) ++z;
}
int main() {
x = false;
y = false;
z = 0;
std::thread t1(f);
std::thread t2(g);
t1.join();
t2.join();
assert(z.load() !=0);
return 0;
}
在我的计算机体系结构课上,我们被告知这段代码中的断言总是成真。但是现在仔细审查后,我真的不明白为什么会这样。
据我所知:
- 带有“ memory_order_release ”的栅栏将不允许在它之后执行先前的存储
- 带有“ memory_order_acquire ”的栅栏将不允许在它之后执行的任何加载在它之前执行。
如果我的理解是正确的,为什么下面的动作序列不能发生?
- 在 t1 内,
y.store(true, std::memory_order_relaxed);
被称为 - t2 完全运行,并且在加载“x”时会看到“假”,因此不会增加单位中的 z
- t1 完成执行
- 在主线程中,断言失败,因为 z.load() 返回 0
我认为这符合 'acquire'-'release' 规则,但是,例如在这个问题的最佳答案中:Understanding c++11 memory fences这与我的情况非常相似,它暗示我的第 1 步在“memory_order_release”之前不能发生一系列动作,但没有详细说明其背后的原因。
我对此感到非常困惑,如果有人能对此有所了解,我将非常高兴:)