std::memory_order_release 必须与同一原子变量上的 load(..., std::memory_order_acquire) 配对才有效;它仅禁止自身前的读写重排到其后,不保证可见性,也不触发缓存同步,唯有 acquire-load 读到该 release 写入的值时,才能确保看到之前所有写入。

单用 std::memory_order_release 不能解决可见性——它必须和 std::memory_order_acquire 在同一个原子变量上配对,才能让非原子写入对另一线程“可观察”。
为什么只在写线程用 store(..., std::memory_order_release) 还不够?
释放操作本身不“推送”数据,也不强制其他线程立即看到该原子变量的新值。它只做一件事:禁止编译器和 CPU 把它前面的读写操作重排到它后面。
- 如果读线程没用
load(..., std::memory_order_acquire)去读这个变量,那写线程的release就像发了个没人监听的信号——没有同步关系可言 - 即使读线程用了
acquire,但目标不是同一个std::atomic对象(比如写flag.store(true, release),却读data.load(acquire)),同步链直接断裂 -
release不保证 cache coherency 协议立刻把数据广播出去,它只保证:一旦读线程通过acquire看到了这个新值,那它就一定能观察到release之前所有写入
std::memory_order_release 必须和哪个操作配对才有效?
必须和同一原子变量上的 load(..., std::memory_order_acquire) 配对。这不是推荐,是 C++ 内存模型的硬性要求:只有这种组合才能建立 synchronizes-with 关系。
- 错误示例:
std::atomic<bool> ready{false}; std::atomic<int> data{0};</int></bool>—— 不能用ready.store(true, release)去同步data的读取,除非你也在data上做 acquire-load(但语义错乱) - 正确模式:一个变量既当“信标”又承载同步语义,例如
std::atomic<bool> ready{false}; int data = 0;</bool>,然后写线程先写data = 42;,再ready.store(true, std::memory_order_release);,读线程循环ready.load(std::memory_order_acquire)直到为 true,之后访问data就安全 - 顺序不可逆:必须写线程先
store(release),读线程后load(acquire);若读线程抢在写线程 store 前完成 load,结果未定义
x86 和 ARM 上 std::memory_order_release 的实际表现差异
语义一致,实现不同。忽略这点是跨平台偶发 bug 的主要来源。
- x86:通常不生成额外 CPU 指令,仅插入编译器 barrier(如
mov后加compiler barrier),所以“看起来总能跑通” - ARM/AArch64:必须生成带语义的指令,如
stlr(store-release),否则无法满足内存模型约束 - 常见踩坑:在 x86 上测试时漏写
release或误用relaxed,一切正常;一上 ARM 就出现data读到旧值或未初始化值——问题不在逻辑,而在缺少 release 所需的硬件级语义指令
容易被忽略的关键点:非原子变量的写入必须严格位于 store(..., release) 之前
这不是“大概早一点”,而是编译器和 CPU 都必须保证的顺序约束。任何穿插在中间的 relaxed 操作、函数调用、甚至空语句,都可能破坏依赖链。
- 安全写法:
data = 42; ready.store(true, std::memory_order_release); - 危险写法:
data = 42; some_relaxed_atomic_op.fetch_add(1, std::memory_order_relaxed); ready.store(true, std::memory_order_release);—— 中间 relaxed 操作可能让编译器/CPU 重新调度data = 42到store后面 - 更隐蔽的陷阱:if 分支、循环、日志打印等看似无害的代码,只要出现在
data赋值和release之间,且没显式同步,就可能引入重排风险
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











