You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

《C++并发编程实战(第2版)》std::memory_order_relaxed示例正确性疑问

关于std::memory_order_relaxed示例输出的解释

先贴出《C++并发编程实战(第2版)》5.6节的核心示例代码(简化版):

#include <atomic>
#include <thread>

std::atomic<int> x{0}, y{0};
std::atomic<int> r1{0}, r2{0};

void thread1() {
    r1 = y.load(std::memory_order_relaxed); // 读y
    x.store(5, std::memory_order_relaxed);  // 写x
}

void thread2() {
    r2 = x.load(std::memory_order_relaxed); // 读x
    y.store(4, std::memory_order_relaxed);  // 写y
}

书中提到的一种合法输出对应你描述的“线程1写x=5时读到y值、线程2写y=4时读到x值”的矛盾场景(你可能记错了初始值或变量值,但核心逻辑一致)。

核心特性:std::memory_order_relaxed的本质

std::memory_order_relaxed是C++内存模型中最弱的原子操作语义,仅保证操作本身的原子性,没有任何线程间的内存序约束:

  • 编译器或CPU可以对单个线程内的relaxed原子操作随意重排(只要不破坏单线程的逻辑正确性);
  • 不建立线程间的happens-before关系;
  • 一个线程的relaxed操作结果,对其他线程的可见性是异步且无顺序保证的。

为何“矛盾”输出合法

你提到的看似逻辑冲突的输出,是两个因素共同作用的结果:

  1. 指令重排:比如线程1的代码逻辑是先读y再写x,但编译器/CPU可能将其重排为先写x再读y;线程2的逻辑是先读x再写y,实际执行时被重排为先写y再读x。由于relaxed不禁止这种重排,完全符合C++标准。
  2. 缓存异步同步:多CPU核心各自拥有独立缓存,relaxed原子操作的结果不会立即同步到所有核心。线程1读到的y值可能是线程2已经写入但还未同步到线程1核心缓存的最新值,反之亦然。

为何Windows 10环境下测不到该结果

Windows主流的x86/x64架构属于强内存模型,对指令重排的限制远多于ARM、PowerPC等弱内存模型架构:

  • x86/x64默认禁止写操作重排到读操作之前,也禁止读操作重排到写操作之后(针对不同内存地址的操作);
  • x86/x64的原子操作默认带有类似acquire/release的部分约束,进一步缩小了relaxed操作的重排空间。

因此在x86/x64平台上,这种极端输出的出现概率极低,几乎无法复现。如果要验证,建议在弱内存模型的架构(如ARM)上测试,或者通过编译器的高优化选项(如-O3)放大重排概率。

内容的提问来源于stack exchange,提问作者coneco

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 16:27:49