以RMW为首的释放序列是否建立同步关系?示例理解是否正确?
以RMW(读-修改-写)为首的释放序列是否会建立同步关系?
代码示例
#include <iostream> #include <atomic> #include <thread> #include <cassert> int main(){ std::atomic<int> v{0}; int x = 0; std::thread t1([&](){ x = 1; v.exchange(1,std::memory_order::release); // #1 }); std::thread t2([&](){ int expected = 1; while(!v.compare_exchange_strong(expected,3,std::memory_order::relaxed)){} // #2 v.fetch_sub(1,std::memory_order::relaxed); // #3 }); std::thread t3([&](){ int expected = 2; while(!v.compare_exchange_strong(expected,10,std::memory_order::relaxed)){} // #4 assert(x ==1); }); t1.join(); t2.join(); t3.join(); }
标准定义引用
根据[intro.races] p5的定义:
以原子对象M上的释放操作A为首的释放序列,是M修改顺序中的一个最大连续子序列,其中第一个操作是A,后续每个操作都是原子读-修改-写(RMW)操作。
问题分析与结论
你提到的理解是正确的,断言永远不会失败,原因如下:
释放序列的构成:#1是带
std::memory_order::release语义的exchange操作,属于释放操作,是释放序列的起点。#2的compare_exchange_strong、#3的fetch_sub都是原子RMW操作,且在v的修改顺序上紧跟#1,因此二者都属于#1为首的释放序列——释放序列对后续RMW操作的内存序没有要求,只要是连续的RMW操作即可。修改顺序与可见性:v的修改顺序为
{0, 1, 3, 2, 10},#4的compare_exchange_strong最终读取到了#3写入的2。根据C++内存模型规则:如果一个线程读取到了某释放序列中任意操作写入的值,那么该释放序列首操作的释放语义会确保首操作之前的所有写入对这个线程可见。断言的安全性:t1中
x = 1发生在#1之前,#1的release语义配合释放序列的传递性,使得t3在执行#4后,x = 1的写入对t3完全可见,因此assert(x == 1)永远不会触发。
内容的提问来源于stack exchange,提问作者xmh0511
相关产品推荐
相关产品推荐

