该内存序是否正确?线程2中的断言是否可能失败?
std::atomic<bool> x{ false }; std::atomic<bool> y{ false }; // thread 1 y.store(true, std::memory_order_seq_cst); x.store(true, std::memory_order_release); // thread2 while (!x.load(std::memory_order_relaxed)); assert(y.load(std::memory_order_seq_cst)); // !!!
上述代码中的断言是否可能失败?我的理解是:尽管读取x采用std::memory_order_relaxed,但一旦线程2观测到线程1对x的写入,就不可能观测到y为false,因为对y的写入happens before对x的写入。
该内存序来自真实场景,本示例中或许可以采用更弱的内存序,但为避免遗漏细节未做修改。
断言不可能失败,你的理解是正确的,核心原因如下:
同一线程的happens-before关系:线程1中,
y.store(true, seq_cst)严格happens beforex.store(true, release)——这是C++内存模型的基础规则:同一线程内按代码顺序执行的操作,前者必然先于后者完成。seq_cst的全局总序特性:所有
std::memory_order_seq_cst的原子操作会形成一个单一的全局执行顺序S。在这个全局顺序里,线程1的y.store必然排在x.store之前。观测到x写入后的传递性:当线程2的
x.load(relaxed)读取到线程1写入的true时,说明在全局顺序S中,线程1的x.store排在这个x.load之前。结合第一步的关系,全局顺序S中线程1的y.store必然排在线程2的y.load(seq_cst)之前,因此y.load一定会读取到true,断言不会触发失败。
哪怕x的读取用了relaxed内存序,只要观测到了线程1对x的写入,就会通过seq_cst的全局总序和同一线程的happens-before关系,保证y的写入对线程2可见。
内容的提问来源于stack exchange,提问作者Andriy Tylychko

