std::atomic实现无锁编程需依赖硬件原子指令,适用于基础整型、指针及满足trivially copyable且lock-free的类型;须显式指定内存序,用compare_exchange_weak构建无锁结构,并规避ABA、内存泄漏等陷阱。

用 std::atomic 实现无锁编程,核心是避免互斥锁(如 std::mutex),靠硬件支持的原子操作保障读写安全。它不等于“完全不用同步”,而是把同步逻辑下沉到单个变量级别,由 CPU 指令(如 LOCK XCHG、CMPXCHG)保证操作不可分割。
哪些类型适合用 std::atomic
基础整型(int、long、bool)、指针,以及满足 trivially copyable 且大小适配原子指令的自定义类型(通常需 static_assert(std::atomic 验证)。浮点数虽有 std::atomic,但部分平台非 lock-free,性能可能打折扣。
- 推荐优先使用
std::atomic、std::atomic、std::atomic - 避免对大结构体(如含 string 或 vector 的类)直接套 atomic —— 编译可能失败或退化为内部加锁
- 用
T.load()和T.store(val)替代直接读写,显式控制内存序
内存序(memory order)不是可选项,是关键设计点
默认 std::memory_order_seq_cst 最强,但开销最大;实际中常根据数据依赖关系降级以提升性能。例如:
- 计数器累加:用
fetch_add(1, std::memory_order_relaxed)足够 —— 只关心数值本身,不依赖其他变量 - 生产者-消费者标志位:写端用
store(true, std::memory_order_release),读端用load(std::memory_order_acquire),确保 release 前的写操作对 acquire 后的读可见 - 自旋等待 flag 变成 true:用
while (!flag.load(std::memory_order_acquire)) { /* pause */ },配合_mm_pause()减少功耗
用 compare_exchange_weak 实现无锁栈/队列的核心技巧
这是无锁数据结构的基石。它做“比较并交换”:仅当当前值等于预期值时才更新,并返回是否成功。weak 版本允许虚假失败(spurious failure),需循环重试。
立即学习“C++免费学习笔记(深入)”;
- 典型模式:
do { expected = top.load(); new_node->next = expected; } while (!top.compare_exchange_weak(expected, new_node)); - 注意:
compare_exchange_weak会修改expected—— 失败时自动更新为当前真实值,下次循环直接重试 - 避免在循环体内做复杂计算或分配内存,否则失败重试成本高
- 若需强保证(如金融场景),可用
compare_exchange_strong,但多数情况 weak 更高效
常见陷阱与规避方式
无锁 ≠ 无脑快。错误假设易引发 ABA 问题、内存泄漏或死循环。
- ABA 问题:指针被释放后又被新对象复用,导致
compare_exchange误判成功。解法:用带版本号的 tag pointer(如std::atomic存高位版本+低位指针) - 忘记 delete 或智能指针管理:无锁结构中节点回收必须延迟(如 Hazard Pointer、RCU 或 epoch-based reclamation),不能立即
delete - 用
atomic_flag做自旋锁?可以,但它只支持 test-and-set,功能有限;更推荐直接用std::atomic+exchange - 调试困难:原子操作无法打断点观察中间态,建议先用
std::mutex验证逻辑,再逐步替换为 atomic








