compare_exchange_weak 的用法

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:交换成功,原子变量被更新为 desired
  • false:交换失败,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:混淆 weakstrong
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

相关推荐
漂流瓶jz1 小时前
UVA-1442 洞穴 题解答案代码 算法竞赛入门经典第二版
c++·算法·题解·aoapc·算法竞赛入门经典·uva
叠层归一研究院2 小时前
基于极限自指的叠层归一宇宙结构理论——无元外部封闭系统的内生区分模型
人工智能·经验分享·算法·agi
Selvaggia3 小时前
Diffusion Model 的基本原理与模型架构
算法
wabs6665 小时前
关于二叉树【力扣572.另一棵树的子树的思考】
数据结构·c++·算法·leetcode·二叉树
hanlin035 小时前
刷题笔记:力扣第41题-缺失的第一个正数
笔记·算法·leetcode
shehuiyuelaiyuehao5 小时前
算法50,分治归并,数组中的逆序对
java·算法
阳明山水6 小时前
校准分位数驱动智能库存决策
人工智能·深度学习·算法·机器学习·架构
别动我齐刘海7 小时前
ROS2 Jazzy + C++ 实战路线——进阶学习3
c++·人工智能·vscode·python·算法·机器学习·机器人
zhangfeng11337 小时前
《从“人工适配“到“智能生成“:KernelSwift 跨国产芯片算子迁移全栈方案解读》 —— 强调范式跃迁和跨硬件属性,适合偏架构分析的写法
人工智能·算法·华为·ai编程·npu
0+1117 小时前
算法 --滑动窗口
c++·算法·leetcode