std::atomic_int多线程Release存储后,Acquire加载能否读取旧值?
假设有一个类型为std::atomic_int的原子变量M,执行以下操作:
- 线程1执行
M.store(1, memory_order_release) - 随后,线程2执行
M.store(2, memory_order_release) - 再之后,线程3执行
M.load(memory_order_acquire)
是否存在合法场景,使得线程3读取到值1而非2?
提问者假设这是不可能的,依据是写-写一致性(write-write coherence)和happens-before(先行发生)特性,但查阅C++标准及cppreference文档后未找到简洁明确的答案,希望获得带有可信参考的解答。
不存在这样的合法场景,线程3不可能读取到值1。核心依据来自C++标准中关于原子操作的修改顺序(modification order)和写-写一致性规则:
原子对象的修改顺序是全序的:对于任何原子对象,所有对它的修改操作(这里是线程1的
store(1)和线程2的store(2))都存在一个全局一致的全序关系。题目中明确线程1的store操作先于线程2的store操作执行,因此在M的修改顺序中,store(1)必然排在store(2)之前。写-写一致性规则:C++标准规定,对于原子对象的两个修改操作A和B,如果A在修改顺序中先于B,那么所有读取该对象的操作,要么读取到B的值,要么读取到在修改顺序中晚于B的值,不可能读取到A的值(除非没有后续修改)。
结合题目中的时序:线程2的store(2)在修改顺序中晚于线程1的store(1),且线程3的load操作发生在线程2的store之后,因此线程3的load只能读取到2,或者后续对M的其他修改值,但绝不可能读取到1。
另外,从happens-before的角度来看,虽然release-acquire本身不直接在非相邻线程间建立happens-before关系,但修改顺序的全序性确保了所有线程对M的修改顺序认知是一致的,后续的load操作必须遵守这个顺序。
内容的提问来源于stack exchange,提问作者Yam Marcovic

