【C/C++】基础能力之原子操作_CAS

CAS

1 什么是CAS?

CAS(Compare-and-Swap)是一种原子操作。
用处:用于在多线程编程中实现无锁(Lock-Free)数据结构。
核心功能是:比较内存中的当前值与预期值,如果两者相同,则将内存值更新为新值;否则不进行修改。整个过程是原子的,即不可被中断。


2 工作原理

CAS操作包含三个参数:

  • 内存地址(Mem):需要修改的内存位置。
  • 预期值(Expected):操作前读取的旧值。
  • 新值(New):希望设置的新值。

执行流程

  1. 读取内存地址的当前值。
  2. 比较当前值与预期值:
    • 相等:将内存值更新为新值,返回成功。
    • 不等:不修改内存,返回失败。

整个过程在硬件层面保证原子性,避免多线程竞争导致的数据不一致。


3 伪代码实现

function CAS(Mem, Expected, New):
    if *Mem == Expected:
        *Mem = New
        return true
    else:
        return false

4 代码示例

在C++中,CAS通过 std::atomic 类型的 compare_exchange_weakcompare_exchange_strong 实现:

#include <atomic>
#include <iostream>

std::atomic<int> counter(0);

void increment_counter() {
    int old_val = counter.load();
    while (!counter.compare_exchange_weak(old_val, old_val + 1)) {
        // CAS失败(old_val已过时),重新加载最新值并重试
    }
}

int main() {
    increment_counter();
    std::cout << "Counter: " << counter << std::endl; // 输出 1
    return 0;
}

5 CAS的应用场景

5.1 无锁数据结构

  • 无锁队列:通过CAS实现线程安全的入队(Enqueue)和出队(Dequeue)。
  • 无锁栈:使用CAS更新栈顶指针。

5.2 同步原语

  • 自旋锁(SpinLock):线程通过CAS竞争锁。
    class SpinLock {
        std::atomic<bool> locked{false};
    public:
        void lock() {
            while (locked.exchange(true)) {} // CAS循环
        }
        void unlock() {
            locked.store(false);
        }
    };
    

5.3 计数器与资源管理

  • 原子计数器:如统计请求次数,避免锁争用。

6 CAS的ABA问题及解决方案

6.1 ABA问题描述

  • 场景:线程A读取内存值为A,准备修改为C。此时线程B将A→B→A,线程A的CAS仍会成功,但实际中间状态已被改变。
  • 风险:可能导致逻辑错误(如链表节点被释放后重用)。

6.2 解决方案

  • 标签指针(Tagged Pointer):在指针高位增加版本号,每次修改递增。
    struct TaggedPointer {
        void* ptr;
        uint64_t tag; // 版本号
    };
    std::atomic<TaggedPointer> atomic_ptr;
    
  • 双字CAS(DCAS):扩展CAS操作位数,同时修改值和版本号(需硬件支持,如x86的CMPXCHG16B)。

7 CAS在不同语言中的实现

语言实现方式示例
C++std::atomic::compare_exchange_weakatomic_val.compare_exchange_weak(old, new)
JavaAtomicInteger.compareAndSet()atomicInt.compareAndSet(old, new)
Goatomic.CompareAndSwapInt32()atomic.CompareAndSwapInt32(&val, old, new)

8 硬件支持

  • x86/x64CMPXCHG(单字)和 CMPXCHG16B(双字)指令。
  • ARMLDREX(加载独占)和 STREX(存储独占)指令组合。
  • RISC-VLR.W(加载保留)和 SC.W(条件存储)指令。

9 CAS的优缺点

优点缺点
无锁,减少线程阻塞需处理ABA问题
高并发性能实现复杂,需循环重试(忙等待)
避免死锁不适用于所有场景(如复杂事务)

10 总结

  1. CAS是并发编程的基石,通过原子比较与交换实现高效的无锁操作。
  2. 核心优势在于避免锁竞争,提升多线程性能,但需谨慎处理ABA问题。
  3. 合理应用于计数器、无锁队列等场景,可显著优化高并发系统性能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值