C++顺序一致性是否保证读取内存最新值?技术问询
C++顺序一致性内存序下的原子操作困惑解析
首先看示例代码:
std::atomic<int> X(0), Y(0); int r1, r2; void thread1() { X.store(1); // 默认使用std::memory_order_seq_cst r1 = Y.load(); // 默认使用std::memory_order_seq_cst } void thread2() { Y.store(1); // 默认使用std::memory_order_seq_cst r2 = X.load(); // 默认使用std::memory_order_seq_cst }
核心问题拆解
- 顺序一致性的核心规则:
std::memory_order_seq_cst要求所有原子操作存在一个全局总序,且这个总序与每个线程内部的程序顺序完全一致——线程内先执行的操作,在全局总序里必然排在后执行的操作前面。 - 断言触发可能性:
assert(r1 != 0 && r2 != 0)是可能触发的,但绝对不会出现r1=0且r2=0的情况:- 比如全局总序为:
thread1的X.store→thread1的Y.load→thread2的Y.store→thread2的X.load,此时r1=0(thread1读取Y时,thread2的Y.store还未执行),r2=1(thread2读取X时,thread1的X.store已完成),断言会触发。 - 反过来,若全局总序是
thread2的Y.store→thread2的X.load→thread1的X.store→thread1的Y.load,则r2=0,r1=1,断言同样会触发。 - 不存在能让
r1=0且r2=0的全局总序:如果r1=0,说明thread2的Y.store在thread1的Y.load之后,而thread2的程序顺序要求Y.store在X.load之前,因此thread2的X.load必然在thread1的Y.load之后;又因为thread1的X.store在Y.load之前,所以thread1的X.store一定在thread2的X.load之前,此时thread2的X.load必须读到1,即r2=1。同理,若r2=0则r1必为1。
- 比如全局总序为:
Preshing与Anthony Williams的说法并不矛盾
- Preshing的表述应该是指不会出现r1和r2同时为0的情况,这完全符合顺序一致性的规则。
- Anthony Williams提到的“仍可能读到旧值”,指的是单个线程可能读到另一线程后续才完成的存储操作的旧值(比如上述例子中r1=0或r2=0的情况),这也完全正确——顺序一致性只保证全局总序的存在,不保证跨线程操作一定能彼此看见,只是约束了可见性的逻辑边界。
内容的提问来源于stack exchange,提问作者Mati
相关产品推荐
相关产品推荐

