欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 教育 > 培训 > 深入解析 CAS 操作

深入解析 CAS 操作

2025/12/14 9:55:57 来源:https://blog.csdn.net/weixin_36755535/article/details/148497551  浏览:    关键词:深入解析 CAS 操作

在这里插入图片描述

一、CAS 的本质:硬件级别的乐观锁

CAS(Compare-And-Swap,比较并交换) 是一种原子操作指令,用于实现对共享变量的无锁并发修改。它是现代多核处理器支持的底层硬件指令,也是构建高效并发数据结构(如锁、队列、计数器)的核心基础。

核心原理
  1. 操作原子性:CAS 操作由硬件保证在执行过程中不会被线程调度打断
  2. 三步合一:将"读取-判断-写入"合并为单个原子操作
  3. 乐观锁机制:假设竞争很少发生,先操作后检测冲突
// CAS 伪代码表示
bool CAS(T* ptr, T expected, T new_value) {if (*ptr == expected) {   // 比较内存当前值*ptr = new_value;     // 交换新值return true;}return false;
}

二、工作流程详解

  1. 读取内存值:获取共享变量当前值 V
  2. 计算新值:基于 V 计算目标值 New
  3. 原子提交
    • 若内存值仍为 V ⇒ 写入 New
    • 若内存值已变化 ⇒ 放弃操作

三、关键优势:突破并发瓶颈

特性传统锁机制CAS 机制
线程阻塞可能发生等待无阻塞
死锁风险存在不存在
性能开销上下文切换代价高仅需单条CPU指令
并发粒度粗粒度细粒度

四、ABA 问题:隐藏的陷阱

问题场景
  1. 线程1读取值 A
  2. 线程2修改 A→B→A
  3. 线程1执行 CAS:检测值仍为 A ⇒ 操作成功

后果:数据看似未变,实际已发生中间状态变更

解决方案
  1. 版本号机制
    // Java AtomicStampedReference 实现
    AtomicStampedReference<String> ref = new AtomicStampedReference<>("A", 0); // 初始版本0ref.compareAndSet("A", "B", 0, 1); // 同时验证值和版本号
    
  2. 时间戳标记:IBM zSeries 的 double-width CAS
  3. 垃圾回收指针:依赖GC防止内存重用(如.NET)

五、编程语言实现案例

Java 的 java.util.concurrent.atomic
// 原子整型自增实现
public final int getAndIncrement() {return unsafe.getAndAddInt(this, valueOffset, 1);
}// Hotspot Unsafe 源码实现
public final int getAndAddInt(Object o, long offset, int delta) {int v;do {v = getIntVolatile(o, offset);   // 读取当前值} while (!compareAndSwapInt(o, offset, v, v + delta)); // CAS重试return v;
}
C++11 原子库
#include <atomic>
std::atomic<int> counter(0);// CAS操作实现自增
int old_val = counter.load();
while (!counter.compare_exchange_weak(old_val, old_val + 1)) {// 优化:允许虚假失败,通常配合循环使用
}

六、典型应用场景

  1. 无锁计数器

    # Python ctypes 访问硬件CAS
    import ctypes
    libc = ctypes.cdll.LoadLibrary('libc.so.6')
    counter = ctypes.c_int(0)def atomic_increment():while True:old = counter.valueif libc.__sync_val_compare_and_swap(ctypes.byref(counter), old, old+1) == old:break
    
  2. 无锁栈实现(Treiber Stack)

    class ConcurrentStack<T> {AtomicReference<Node<T>> top = new AtomicReference<>();void push(T item) {Node<T> newHead = new Node<>(item);Node<T> oldHead;do {oldHead = top.get();newHead.next = oldHead;} while (!top.compareAndSet(oldHead, newHead));}T pop() {Node<T> oldHead;Node<T> newHead;do {oldHead = top.get();if (oldHead == null) return null;newHead = oldHead.next;} while (!top.compareAndSet(oldHead, newHead));return oldHead.item;}
    }
    
  3. 无锁队列(Michael-Scott 队列)

    type Node struct {value interface{}next  *Node
    }type Queue struct {head *Nodetail *Node
    }func (q *Queue) Enqueue(v interface{}) {node := &Node{value: v}for {last := q.tailnext := last.nextif last == q.tail { // 验证状态未变if next == nil {if atomic.CompareAndSwapPointer(&last.next, nil, node) {atomic.CompareAndSwapPointer(&q.tail, last, node)return}} else {atomic.CompareAndSwapPointer(&q.tail, last, next)}}}
    }
    

七、底层硬件支持架构

处理器架构CAS 指令位宽支持
x86/x86-64CMPXCHG8/16/32/64位
ARMv8LDXR + STXR(LL/SC模型)64位
POWERlwarx + stwcx64位
RISC-Vlr.w + sc.w32/64/128位

LL/SC(Load-Link/Store-Conditional):现代RISC架构采用的替代实现方案

  1. Load-Link:标记内存区域
  2. 执行计算
  3. Store-Conditional:当标记区域未被修改时写入

八、性能优化策略

  1. 缓存行填充避免伪共享

    // C++ 缓存行对齐结构
    struct alignas(64) AtomicCounter {std::atomic<int> value;char padding[64 - sizeof(std::atomic<int>)];
    };
    
  2. 指数退避减少竞争

    while (!casSuccess) {int delay = random.nextInt(baseDelay);for (int i = 0; i < delay; i++) Thread.yield(); // 让出CPUbaseDelay *= 2; // 指数级增加等待
    }
    
  3. 批量操作减少CAS调用

    // 批量增加计数器
    func (c *Counter) Add(n int) {const batchSize = 32for n > 0 {batch := nif batch > batchSize {batch = batchSize}// 单次CAS更新批量值c.accumulate(batch) n -= batch}
    }
    

九、局限性及替代方案

  1. 循环开销问题:高竞争场景下自旋消耗CPU

    • 解决方案:java.util.concurrent.locks.LockSupport.park()
  2. 单一变量限制:无法原子修改多个独立变量

    • 替代方案:事务内存(Transactional Memory)
  3. 优先级颠倒风险:低优先级线程持有CAS导致高优先级饥饿

    • 实时系统解决方案:优先级继承协议
  4. 内存顺序约束

    // C++ 内存顺序控制
    counter.compare_exchange_weak(old_val, new_val,std::memory_order_acq_rel,  // 成功时的内存序std::memory_order_acquire   // 失败时的内存序
    );
    

十、现代发展方向

  1. 128位 CAS 扩展:用于原子更新指针+元数据(如指针标记)

    bool __atomic_compare_exchange_16(void* ptr, __int128* expected,__int128 desired
    );
    
  2. 持久内存 CAS:Intel Optane PMEM 的持久化原子操作

    bool pmemobj_atomic_compare_exchange(PMEMoid *ptr, uint64_t *expected_oid,uint64_t desired_oid
    );
    
  3. GPU 原子操作:NVIDIA CUDA 的全局内存原子CAS

    int atomicCAS(int* address, int compare, int val);
    
  4. 分布式 CAS:跨多节点的分布式原子操作协议

    参与者 → 协调者:CAS请求
    协调者 → 所有节点:预提交
    节点响应符合条件 → 协调者:投票
    多数同意 → 协调者:提交指令
    

总结:CAS 的核心价值

CAS 操作通过硬件级原子指令,实现了:

  • 无锁并发:消除传统锁的开销
  • 非阻塞算法:提升系统响应能力
  • 细粒度同步:实现高性能并发数据结构

尽管存在 ABA 问题、高竞争场景性能下降等局限,但通过版本号机制、缓存优化等手段可有效缓解。作为现代并发编程的基石,CAS 在操作系统内核、数据库系统、中间件等高性能系统中发挥着不可替代的作用。理解其原理和最佳实践,是构建高性能并发系统的必备技能。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com