

新闻资讯
技术百科compare_exchange_weak 可能虚假失败是因为底层LL/SC架构(如ARM)允许stxr即使值匹配也失败,这是硬件特性而非bug;weak放弃兜底以换性能,需配合do-while循环使用。
compare_exchange_weak 在底层可能被编译器或硬件映射为一条非原子的“加载-比较-条件存储”序列(如 x86 的 cmpxchg 是强的,但 ARM 的 ldxr/stxr 对本身就允许 spurious failure)。这意味着即使当前值等于期望值,它也可能返回 false,不修改目标值,也不保证重试一定能成功——纯粹是硬件/指令集特性导致的“假失败”。
这不是 bug,而是设计取舍:weak 版本放弃对这类失败的兜底处理,换来更低的指令开销和更高的并发吞吐。
compare_exchange_weak 在循环中反复失败,但 load() 显示值始终没变
xchange_strong?当你需要「一次调用,语义确定」——即:只要当前值等于期望值,就必须成功更新并返回 true。这在非循环逻辑、状态机跃迁、或仅尝试一次的场景中不可妥协。
std::call_once 底层)、资源首次注册、或者作为更大原子操作中的关键判断分支if (flag.compare_exchange_strong(expected, desired)) { ... },你依赖的是“成功即发生”,不能容忍假失败干扰控制流绝大多数无锁数据结构(栈、队列、计数器)的 CAS 循环,都应优先写 compare_exchange_weak。它的轻量特性在高并发下更友好,且循环本身已天然吸收了虚假失败。
Node* old_head = head.load();
Node* new_head;
do {
new_head = old_head->next;
} while (!head.compare_exchange_weak(old_head, new_head));weak 是合理的:循环体足够简单,失败后重新读 old_head 成本低strong,在 ARM 上可能多一次 ldxr + 条件重试,而 weak 失败后直接下一轮 loop,实际更快strong 减少重试次数——但这往往说明设计该优化了compare_exchange_weak 和 compare_exchange_strong 都接受两个 memory_order 参数(success/failure),但很多人只传 std::memory_order_seq_cst,忽略了 failure 路径其实可以更宽松。
std::memory_order_relaxed 即可cas(..., std::memory_order_seq_cst, std::memory_order_seq_cst) —— 多余的全局顺序开销cas(..., std::memory_order_acq_rel, std::memory_order_acquire)(成功时带 acquire+release,失败时只需 acquire 保证重读有效)weak/strong 的选择和 memory_order 是正交问题,但混在一起容易放大性能偏差。虚假失败本身不改变内存序语义,但 failure 的 order 设得太强,会拖慢整个循环。