ARM与x86的std::atomic内存序表现不一致,根源在于ARM采用弱内存模型而x86采用强内存模型,导致相同代码在两平台上的语义、开销及指令生成均不同。
ARM 使用弱内存模型(Weak Memory Model),x86 使用强内存模型(Strong Memory Model)。这意味着相同 C++ 代码在两种架构上,std::atomic 的默认行为和显式内存序的实际开销、语义约束都不同。不是“实现不同”,而是硬件不保证某些重排,编译器和运行时必须用额外指令补足。
std::memory_order_relaxed 几乎无成本,ARM 上可能插入 dmb ish
x86 的 store-store、load-load、load-store 重排被硬件禁止,所以多数 std::atomic 操作(即使是 relaxed)无需内存屏障指令。ARM 则不然:即使 relaxed store,也可能被乱序到后续非原子访存之后,因此编译器常插入 dmb ish(inner shareable domain barrier)来满足 C++ 标准对“修改顺序一致性”的最低要求(尤其在多核间可见性上)。
std::atomic x{0}, y{0}; ,线程 A 执行 x.store(1, std::memory_order_relaxed); y.store(1, std::memory_order_relaxed);,线程 B 观察到 y==1 && x==0 在 x86 不可能,在 ARM 
std::memory_order_release/acquire 或显式 barrierrelaxed store 常生成 str w0, [x1] + dmb ish;x86-64 下通常只有 mov dword ptr [rdi], esi
std::memory_order_seq_cst 在 ARM 上代价显著更高x86 天然提供顺序一致性(SC)语义,seq_cst load/store 通常不额外生成 barrier 指令(仅部分 store 可能加 mfence)。ARM 必须为每个 seq_cst 操作插入 full barrier(dmb ish),且 load-use 和 store-store 之间还需配对控制(例如 ldar/stlr 指令本身带 acquire/release 语义,但组合成 SC 需额外同步)。
// ARM64 Clang 15 -O2 生成的 seq_cst store mov x8, #1 stlr w8, [x0] // store-release dmb ish // 强制全局顺序,x86 下这行通常不存在
seq_cst 会显著拖慢 ARM 多核性能,尤其在高争用计数器场景memory_order_acquire/release,避免无谓升级为 seq_cst
seq_cst 的优化策略不同,ARM 下 GCC 更倾向插入 dmb,Clang 可能复用 ldar/stlr 的隐含语义,但跨操作的顺序仍需 barrierldar/stlr 指令不等于 x86 的 mov + 缓存一致性x86 的 cache coherency 协议(MESIF/MOESI)天然保证所有核看到一致的写顺序,而 ARM 的 ldar(load-acquire)和 stlr(store-release)是**语义指令**,它们不保证全局顺序,只约束当前核的指令重排,并配合 dmb 实现跨核同步。误以为 “用了 stlr 就自动全序” 是常见误区。
stlr 保证该 store 不会重排到其后的任何访存之前,但不保证其他核立即看到 —— 还需 cache line 的 write-back 和 snoop 响应LDAPR(load-acquire, prefetch)等变种,但标准 std::atomic 实现不依赖这些扩展std::atomic 代码时,最易被忽略的是:你以为的“安全重排”在 ARM 上根本不会发生,而你以为的“自然顺序”在 ARM 上必须靠显式内存序兜底。别依赖 x86 的宽容去验证正确性。