CodeWalk

std::atomic的load/store与memory_order详解

作者:孤独的心 · 2026-05-30 12:55

std::atomic::load()和store()在底层对应哪些CPU指令?不同memory_order参数(relaxed/consume/acquire/release/acq_rel/seq_cst)对编译器优化和CPU指令生成有什么影响?如何选择正确的内存序?

回答

孤独的心

x86上的指令生成

  • relaxed:普通mov指令(不阻止任何重排)
  • acquire(load):普通mov指令(x86的读取自带acquire语义,不会将后续指令重排到加载前)
  • release(store):普通mov指令(x86的写入自带release语义,不会将先前指令重排到写入后)
  • seq_cst(store):mov + mfence(或使用xchg指令,其自带锁语义)
  • seq_cst(load):普通mov

ARM上的差异

  • relaxed:普通ldr/str
  • acquire(load):ldar(Load-Acquire Register)
  • release(store):stlr(Store-Release Register)
  • seq_cst:dmb ish + 普通指令,或特殊的ldar/stlr

含义: | memory_order | Load(读)效果 | Store(写)效果 | |-------------|-------------|-------------| | relaxed | 仅原子性,无顺序约束 | 仅原子性 | | consume | 控制依赖(已弃用,不建议用) | - | | acquire | 后续读写不能重排到此load之前 | - | | release | - | 先前读写不能重排到此store之后 | | acq_rel | 同acquire | 同release | | seq_cst | 全局顺序一致(最严格) | 全局顺序一致 |

选择指南

  1. 只有计数器累加→relaxed
  2. 发布-获取模式(flag/数据发布)→acquire+release
  3. 默认:seq_cst(最简单正确,但x86上无额外开销,ARM上略有)
  4. 性能关键路径且理解内存模型→优化为更弱的order
  5. 不要使用consume(C++17已弃用,C++20无提升)

错误案例:用relaxed实现自旋锁错误(需要acquire/release)。