compare_exchange_weak 是 C++ 原子库中用于执行比较并交换(CAS) 操作的函数,它原子地比较原子变量的当前值与期望值,如果相等则更新为目标值,否则更新期望值为当前值。
cpp
bool compare_exchange_weak(T& expected, T desired,
std::memory_order success = std::memory_order_seq_cst,
std::memory_order failure = std::memory_order_seq_cst) noexcept;
| 参数 | 类型 | 说明 |
|---|---|---|
expected |
T&(引用) |
期望值。成功时不变;失败时被更新为原子变量的当前值 |
desired |
T |
目标值。成功时原子变量被更新为此值 |
success |
memory_order |
成功时的内存序(默认最严格) |
failure |
memory_order |
失败时的内存序(默认最严格) |
返回值:
true:交换成功,原子变量被更新为desiredfalse:交换失败,expected被更新为原子变量的当前值
关键点 :整个操作是原子的,不可中断。
核心行为(伪代码)
cpp
bool compare_exchange_weak(T& expected, T desired) {
if (atomic_value == expected) {
atomic_value = desired; // 成功:更新原子变量
return true;
} else {
expected = atomic_value; // 失败:更新期望值为当前值
return false;
}
}
典型用法:循环内重试
由于 weak 可能虚假失败,必须配合循环使用:
cpp
std::atomic<int> val(10);
// 正确用法:do-while 循环
int expected = val.load();
do {
int desired = expected * 2; // 计算新值
} while (!val.compare_exchange_weak(expected, desired));
// 或者使用 while 循环
int expected = val.load();
while (!val.compare_exchange_weak(expected, expected * 2)) {
// expected 已被更新为最新值,继续重试
}
实际应用场景
1. 原子计数器
cpp
std::atomic<int> counter(0);
void increment() {
int expected = counter.load();
while (!counter.compare_exchange_weak(expected, expected + 1)) {
// expected 自动更新为最新值,继续重试
}
}
2. 自旋锁
cpp
std::atomic<bool> lock(false);
void acquire_lock() {
bool expected = false;
while (!lock.compare_exchange_weak(expected, true)) {
expected = false; // 重置 expected,准备下次尝试
}
}
void release_lock() {
lock.store(false);
}
3. 无锁栈的 push 操作
cpp
struct Node { int value; Node* next; };
std::atomic<Node*> head(nullptr);
void push(int val) {
Node* new_node = new Node{val, nullptr};
Node* expected = head.load();
do {
new_node->next = expected;
} while (!head.compare_exchange_weak(expected, new_node));
}
常见错误
错误1:不使用循环
cpp
// ❌ 错误:可能虚假失败
int expected = val.load();
val.compare_exchange_weak(expected, desired); // 可能无声失败
错误2:循环内不更新 expected
cpp
// ❌ 错误:expected 没有重置
while (!val.compare_exchange_weak(expected, desired)) {
// expected 已被更新,但这里没有重新计算 desired
// 如果 desired 依赖于 expected,需要重新计算
}
错误3:混淆 weak 和 strong
cpp
// ❌ 错误:单次尝试用 weak
if (flag.compare_exchange_weak(expected, true)) { // 可能虚假失败
// 获取锁
}
// ✅ 正确:单次尝试用 strong
if (flag.compare_exchange_strong(expected, true)) {
// 获取锁
}
总结
| 场景 | 推荐函数 | 说明 |
|---|---|---|
| 循环内重试(自旋锁、无锁队列) | compare_exchange_weak |
性能更高,循环处理虚假失败 |
| 单次尝试(无循环) | compare_exchange_strong |
保证无虚假失败,更可靠 |
| 低竞争环境 | weak + 循环 |
最高性能 |
| 需要代码简洁性 | strong |
避免手动重试 |
最佳实践 :在循环中优先使用 weak,非循环场景使用 strong。