C++ 原子操作(Atomic Operations)是什么?(如何实现无锁编程)

2次阅读

std::atomic仅保证单变量读写原子性,非万能锁;需配合memory_order解决内存序问题,避免重排导致数据未初始化;慎用伪失败的compare_exchange_weak,false sharing需对齐隔离。

C++ 原子操作(Atomic Operations)是什么?(如何实现无锁编程)

std::atomic 不是线程安全的万能锁

它只是对单个变量的读写提供原子性保证,不是自动保护整个逻辑块。比如两个 std::atomic 变量之间的操作(如先读 A 再根据 A 更新 B)依然可能被其他线程打断,这不是 std::atomic 能解决的。

常见错误现象:data_readystd::atomic,但生产者写完数据后才设为 true,消费者却没加内存序约束,导致看到 true 却读到未初始化的数据 —— 这是编译器重排或 CPU 乱序导致的,不是原子性失效,而是内存序缺失。

  • 必须配合内存序(memory_order)使用,最常用的是 memory_order_acquire(读)和 memory_order_release(写)
  • memory_order_relaxed 仅保证原子性,不约束前后指令顺序,适合计数器等无依赖场景
  • 不要用 std::atomic 模拟自旋锁:它不提供等待语义,应改用 std::atomic_flag + test_and_set()

std::atomic_flag 是唯一保证无锁(lock-free)的原子类

c++ 标准只要求 std::atomic_flag 必须是 lock-free 的,其它 std::atomic 类型是否 lock-free 取决于平台和大小。比如在 x86-64 上 std::atomic 通常是 lock-free,但在某些嵌入式平台可能退化为内部加锁实现。

使用场景:实现自旋锁、轻量级信号量、无锁队列的 head/tail 指针更新。

立即学习C++免费学习笔记(深入)”;

  • 检查是否 lock-free:flag.is_lock_free()ATOMIC_FLAG_INIT 初始化后调用 is_lock_free()
  • 必须用 ATOMIC_FLAG_INIT 初始化,不能用 = {} 或默认构造
  • test_and_set() 默认是 memory_order_seq_cst,如需性能可显式传入 memory_order_acquire

compare_exchange_weak 和 compare_exchange_strong 的区别不是“弱”和“强”,而是“允许伪失败”

compare_exchange_weak 在某些平台(尤其是 LL/SC 架构如 ARM、RISC-V)可能因外部干扰(如中断、缓存同步)返回 false,即使当前值等于期望值。这不是 bug,是硬件特性。

错误做法:把 compare_exchange_weak 当成一次性的条件更新,不重试就继续往下走。

  • 几乎所有循环 CAS 场景都该用 compare_exchange_weak,因为伪失败成本低,且循环本身已处理重试逻辑
  • compare_exchange_strong 保证“值相等就一定成功”,但可能更慢(x86 上两者汇编相同,ARM 上 strong 可能多几条指令)
  • 非循环场景(如只试一次)才考虑 strong,但要意识到它仍可能失败(比如值本来就不等)

无锁编程 ≠ 没有同步开销,反而更容易写出正确但低效的代码

原子操作本身比普通读写贵得多:x86 上 mov 是 1 cycle,lock xadd 是 20–100+ cycles;更麻烦的是 cache line bouncing —— 多个线程频繁修改同一 cache line 中的不同原子变量,会反复使彼此的 cache line 无效。

典型坑:std::atomic a, b, c; 放在一起,三个变量落在同一个 64 字节 cache line 内,A 线程改 a,B 线程改 b,也会互相拖慢。

  • alignas(64) 对齐每个原子变量,或插入 char padding[64] 避免 false sharing
  • 别为了“无锁”而无锁:如果临界区短、竞争低,std::mutex 实际更快,也更易维护
  • 调试困难:竞态不会稳定复现,TSAN 可检测部分问题,但无法覆盖所有内存序误用

真正难的从来不是怎么写原子操作,是怎么画清楚变量间的依赖关系、确定哪些顺序必须保留、哪些可以放松 —— 这些没法靠查文档解决,得靠对硬件模型和具体场景的双重理解。

text=ZqhQzanResources