在 C++ 中,CAS(Compare-And-Swap)操作主要通过 <atomic> 头文件中的 std::atomic 类模板提供的成员函数 compare_exchange_weak 和 compare_exchange_strong 来实现。
1. CAS 的核心逻辑
CAS 操作包含三个操作数:
内存值 (V):要更新的变量的值。 预期原值 (E, Expected):线程认为该变量当前应该有的值(通常是之前读取的快照)。 新值 (N, New):线程想要写入的新值。
原子操作流程如下,核心是比较、交换、重复:
比较:检查内存位置 V 的当前值是否等于预期值 E。 交换(如果相等):如果相等 (V == E),说明在读取后没有其他线程修改过该变量,则将 V 更新为新值 N。操作成功,返回
true。 重试/失败(如果不相等):如果不相等 (V != E),说明有其他线程抢先修改了该变量。此时不进行更新,并将内存中的最新值 V 赋值给预期值 E(这样下次重试时就有了最新的参照)。操作失败,返回false。
2. C++ 中的 CAS 函数
在 C++ 中,std::atomic 提供了两个版本的 CAS:
A. compare_exchange_weak (弱 CAS)
即使内存中的值与预期值相等,它也可能返回 false,称为'伪失败'。
原因在于在某些硬件架构(如 ARM、PowerPC)上,CAS 是通过 LL/SC 指令实现的,上下文切换等因素可能导致 SC 指令失败。
适用场景:循环算法中。因为在循环中,伪失败只会导致多一次循环,而
weak版本在某些平台上通常比strong版本性能更高。
B. compare_exchange_strong (强 CAS)
只有当内存值确实不等于预期值时才会返回 false。
适用场景:非循环的操作,或者当重试的代价非常昂贵时。它在内部可能已经包含了一个小循环来处理伪失败。
3. 代码示例:标准的 CAS 循环
这是最经典的使用模式,用于原子地修改一个变量,向栈中压入一个元素。
#include <atomic>
#include <iostream>
struct Node {
int data;
Node* next;
};
std::atomic<Node*> head(nullptr);
void {
Node* new_node = Node{data, };
Node* expected = head.();
{
new_node->next = expected;
} (!head.(expected, new_node));
}


