C++11顺序一致性内存序是否禁止存储缓冲区Litmus测试出现r1、r2均为0的结果?
// 初始状态 std::atomic<int> x(0), y(0); // 线程1 // 线程2 x.store(1); y.store(1); auto r1 = y.load(); auto r2 = x.load();
结论
在所有操作均使用memory_order_seq_cst(std::atomic默认内存序)的前提下,不可能出现r1和r2同时为0的情况,该结果是被C++内存模型明确禁止的。
规则推导过程
你提到的memory_order_seq_cst的全局全序规则,刚好就是禁止这个结果的核心约束:
所有标记为memory_order_seq_cst的操作,必须存在一个所有线程都观测一致的全局总执行顺序,我们可以基于这个总序做推导:
两个写操作x.store(1)(记为Sx)和y.store(1)(记为Sy)在全局总序里必然有先后关系,只会出现两种可能:
- 全局总序中Sx执行在Sy之前:
线程2的执行顺序是先执行Sy,再执行x.load()(记为Lx),因此Lx在全局总序中的位置一定晚于Sy,也就晚于Sx。SC加载要求能看到全局总序中排在它之前的所有对该变量的修改,因此Lx必然读到x=1,r2不可能为0。 - 全局总序中Sy执行在Sx之前:
同理,线程1的y.load()(记为Ly)在全局总序中的位置晚于Sx,也就晚于Sy,因此Ly必然读到y=1,r1不可能为0。
两种场景下都不可能出现r1、r2同时为0的结果,所以该结果被明确禁止。
补充说明
如果把操作的内存序换成memory_order_release(存储)+memory_order_acquire(加载),那么r1和r2同时为0的结果是被允许的。因为acquire-release语义没有要求不同线程对无关变量的写操作存在全局一致的顺序,两个线程的写操作可以都晚于对方的读操作,从而出现都读到初始值0的情况,这也正是memory_order_seq_cst和acquire-release语义的核心差异之一。
内容的提问来源于stack exchange,提问作者zanmato
相关产品推荐
相关产品推荐

