宽松的记忆顺序会导致无限循环吗?

Lin*_*gxi 8 c++ concurrency atomic memory-model c++11

有问题的代码:

#include <atomic>
#include <thread>

std::atomic_bool stop(false);

void wait_on_stop() {
  while (!stop.load(std::memory_order_relaxed));
}

int main() {
  std::thread t(wait_on_stop);
  stop.store(true, std::memory_order_relaxed);
  t.join();
}
Run Code Online (Sandbox Code Playgroud)

由于std::memory_order_relaxed用在这里,我假设编译器可以自由地重新排序stop.store()t.join().结果,t.join()永远不会回来.这个推理是否正确?

如果是的话,将改变stop.store(true, std::memory_order_relaxed)stop.store(true)解决这一问题?

T.C*_*.C. 6

[简介.进度]/18:

实现应确保原子或同步操作分配的最后一个值(按修改顺序)将在有限的时间内对所有其他线程可见。

[原子顺序]/12:

实现应该使原子存储在合理的时间内对原子加载可见。

这是一项不具约束力的建议。如果您的实现遵循它们(高质量的实现应该如此),那就没问题。否则,你就完蛋了。在这两种情况下,无论使用的内存顺序如何。


C++抽象机没有“重新排序”的概念。在抽象语义中,主线程存储到原子中然后被阻塞,因此如果实现使存储在有限的时间内对加载可见,那么另一个线程将在有限的时间内加载此存储的值,并且终止。相反,如果实现出于某种原因不这样做,那么您的另一个线程将永远循环。使用的内存顺序无关紧要。

我从来没有发现关于“重新排序”的推理有用。它将低级实现细节与高级内存模型混合在一起,并且往往使事情变得更加混乱,而不是更少。