CAS是C++无锁编程的核心,通过compare_exchange_weak/strong实现原子性条件更新,前者在循环中更高效但可能伪失败,后者保证仅值不匹配时失败,常用于无锁计数器等场景,依赖硬件指令如CMPXCHG确保原子性。

在C++的无锁编程中,std::atomic 是实现线程安全操作的核心工具之一。其中最关键的操作就是CAS(Compare-and-Swap),它允许在不使用互斥锁的前提下完成原子性的条件更新,是构建无锁数据结构如无锁队列、无锁栈的基础。
什么是CAS操作?
CAS(Compare-and-Swap)是一种原子指令,用于判断某个内存位置的当前值是否等于预期值,如果是,则将其更新为新值;否则不做修改。这个过程是原子的,不会被其他线程打断。
在 std::atomic 中,CAS 通过两个成员函数实现:
- compare_exchange_weak()
- compare_exchange_strong()
这两个函数都遵循相同的语义:比较原子对象的当前值与期望值,若相等则写入新值,并返回 true;否则将当前值写回期望值变量,并返回 false。
立即学习“C++免费学习笔记(深入)”;
compare_exchange_weak 与 compare_exchange_strong 的区别
两者功能相似,但在某些平台上(如x86以外的架构),weak 版本可能偶尔失败,即使值实际上匹配。这种“伪失败”是为了获得更高的性能,特别是在循环中使用时。
通常建议在循环中使用 compare_exchange_weak,因为它在某些架构上更高效:
std::atomicvalue{0}; int expected = value.load(); while (!value.compare_exchange_weak(expected, desired)) { // 如果失败,expected 已被更新为当前实际值 // 可以选择重新计算 desired 或退出 }
而 compare_exchange_strong 保证只有在值不匹配时才失败,适合不需要循环或对失败敏感的场景。
CAS 在无锁编程中的典型应用
利用 CAS 可以实现诸如无锁计数器、无锁链表节点插入等操作。例如,一个简单的无锁递增可以通过 CAS 实现:
void lock_free_increment(std::atomic& counter) { int expected = counter.load(); int desired; while (true) { desired = expected + 1; if (counter.compare_exchange_weak(expected, desired)) { break; // 成功更新 } // 失败时,expected 被更新为当前值,继续重试 } }
这个模式称为“读-改-重试”循环,是无锁编程中最常见的结构。
底层实现依赖硬件原子指令
std::atomic 的 CAS 操作最终会编译成对应平台的原子汇编指令,比如:
- x86/x64 上的 CMPXCHG 指令
- ARM 上的 LDXR/STXR 或 LDAXR/STLXR 指令对
这些指令由CPU提供支持,确保操作的原子性,不会被中断或与其他核心冲突。
编译器和标准库会根据类型大小和平台选择合适的原子实现方式,对于无法直接支持的类型,可能禁用原子操作或产生编译错误。
基本上就这些。CAS 是 C++ 无锁编程的基石,掌握 compare_exchange_weak/strong 的使用方法和重试逻辑,是编写高效、安全并发结构的关键。











