compare_exchange_weak必须在循环中使用且expected为非const左值引用,否则因伪失败无法更新expected导致死循环;它允许虚假失败以换取ARM等平台更优性能,而compare_exchange_strong仅在值真实不等时失败。

必须写在循环里,且 expected 必须是非 const 的可修改左值引用——漏掉任一条件,大概率死循环或逻辑错误。
为什么 compare_exchange_weak 总是返回 false?
常见现象:刚初始化 std::atomic,设 expected = 0,调一次 compare_exchange_weak(expected, 1) 就返回 false,但值明明没被改过。
原因有两个:
-
compare_exchange_weak允许伪失败(spurious failure),尤其在 ARM 等弱内存模型平台; - 它会在失败时把当前值写回
expected—— 如果expected是字面量、临时变量或const int&,函数无法更新它,下次重试仍用旧值,导致无限失败。
✅ 正确写法:
int expected = atomic_var.load();
while (!atomic_var.compare_exchange_weak(expected, desired)) {
// expected 已被更新为当前值,可直接重试
}
❌ 错误写法(只调一次,expected 不更新):
int expected = 0; atomic_var.compare_exchange_weak(expected, 1);
❌ 危险写法(expected 绑定到 const,无法覆写):
const int exp = atomic_var.load(); atomic_var.compare_exchange_weak(exp, 1);
compare_exchange_weak 和 compare_exchange_strong 怎么选?
不是“强就一定好”,而是看失败容忍度和性能敏感度:
-
compare_exchange_weak在 x86 上通常和strong性能一致;但在 ARM 上生成更轻量指令(如LDAXR/STLXR),代价是允许伪失败; -
compare_exchange_strong保证仅当值真实不等才失败,但重试成本更高(可能多一次原子读)。
推荐策略:
- 所有循环重试场景(无锁栈
push/pop、计数器递增、状态机跃迁)→ 优先用weak; - 单次尝试逻辑(如初始化标志位)、失败需触发昂贵回退(日志+告警)、或伪失败会破坏业务语义(如金融事务提交)→ 用
strong; - 混合策略可行:前 N 次用
weak,失败后切strong,避免极端争用下伪失败堆积。
双内存序重载的 failure 参数不能乱设
使用双内存序版本时:compare_exchange_weak(expected, desired, success, failure),failure 受严格限制:
-
failure内存序不能强于success; -
failure不能是memory_order_release或memory_order_acq_rel(失败路径无写操作); - 若
success == memory_order_acq_rel,则failure隐式为memory_order_acquire; - 若
success == memory_order_release,则failure隐式为memory_order_relaxed。
多数场景用单参数版(默认 memory_order_seq_cst)更安全;真要优化,先确认硬件平台和同步语义,别为省几条指令引入重排序 bug。
最易忽略的点:伪失败不是 bug,是设计特性;expected 被覆写也不是副作用,是接口契约。写错循环结构或传错引用类型,问题不会立刻暴露,而是在高并发、跨平台或压力测试时突然崩掉。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











