当前位置: 首页 > ops >正文

深入解析 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 在操作系统内核、数据库系统、中间件等高性能系统中发挥着不可替代的作用。理解其原理和最佳实践,是构建高性能并发系统的必备技能。

http://www.xdnf.cn/news/12568.html

相关文章:

  • Linux 系统、代码与服务器进阶知识深度解析
  • 【Python】当前最稳定3.12版本安装,基于Anaconda的环境配置及换源
  • 力扣面试150题--除法求值
  • 计算矩阵A和B的乘积
  • 基于Python学习《Head First设计模式》第八章 模板方法模式
  • Readest(电子书阅读器) v0.9.53
  • 缓存一致性 与 执行流
  • STM32学习笔记:外部中断(EXTI)原理与应用详解
  • 什么是可恢复保险丝
  • 永恒之蓝(CVE-2017-0146)详细复现
  • day49 python 注意力热图
  • Oracle 客户端深度指南:SQL Developer 与 PL/SQL Developer 全面安装使用教程
  • MySQL中的内置函数
  • 深入剖析Nginx:从入门到高并发架构实战
  • day24 元组和OS模块
  • 十、【ESP32开发全栈指南: TCP客户端】
  • LinkedList、Vector、Set
  • 嵌入式学习笔记 - freeRTOS vTaskPlaceOnEventList()函数解析
  • VirtualBox启动失败@Ubuntu22.04 说是配置文件有问题
  • 使用ORM Bee (ormbee) ,如何利用SQLAlchemy的模型生成数据库表.
  • “组件、路由懒加载”,在 Vue3 和 React 中分别如何实现? (copy)
  • 使用Python和Flask构建简单的机器学习API
  • MySQL事务与锁中的MVCC 深度解析与面试题讲解
  • Spring AI 核心工作流
  • 每日Prompt:治愈动漫插画
  • 基于深度学习的金枪鱼各类别目标检测含完整数据集
  • Strong Baseline: Multi-UAV Tracking via YOLOv12 with BoT-SORT-ReID 2025最新无人机跟踪
  • 【C/C++】实现固定地址函数调用
  • 2种官方方法关闭Windows防火墙
  • iOS、Android、鸿蒙、Web、桌面 多端开发框架Kotlin Multiplatform