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

CAS详解

1. CAS 核心概念
  • 定义Compare And Swap(比较并交换),一种无锁并发控制技术。
  • 核心逻辑
    内存值 V,预期值 A,新值 B。
    当且仅当 V == A 时,将 V 更新为 B,否则不操作。
    整个操作由 CPU 保证原子性。
    
  • 原子性保证:依赖 CPU 的 cmpxchg 指令(多核下通过总线锁定或缓存锁实现)。

2. CAS 底层实现
  1. Unsafe 类

    • 作用:Java 通过 sun.misc.Unsafe 类直接操作内存,调用本地方法(Native Method)实现 CAS。
    • 关键方法compareAndSwapInt(), compareAndSwapLong() 等。
    • 示例AtomicIntegerincrementAndGet() 底层通过循环 CAS 实现:
      public final int incrementAndGet() {return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
      }
      
  2. CPU 指令

    • cmpxchg 指令:多核环境下通过缓存锁(MESI 协议)或总线锁保证原子性。

3. CAS 在 JUC 中的应用
  1. 原子类(Atomic Classes)

    • 常用类AtomicInteger, AtomicLong, AtomicReference
    • 核心方法compareAndSet(expected, newValue)
    • 优化类LongAdder(分散热点,减少 CAS 竞争)。
  2. AQS(AbstractQueuedSynchronizer)

    • 同步状态管理:通过 CAS 修改 volatile int state 实现锁的获取与释放。
    • CLH 队列:CAS 将竞争失败的线程封装为 Node 插入队列尾部。
  3. 并发容器

    • ConcurrentHashMap:插入桶节点时使用 CAS 避免锁竞争。
    • CopyOnWriteArrayList:写操作通过 CAS 复制新数组保证原子性。

4. CAS 的缺陷与解决方案
问题原因解决方案
ABA 问题值从 A → B → A,CAS 无法感知中间变化使用 AtomicStampedReference(版本号)或 AtomicMarkableReference
自旋开销高并发下 CAS 失败导致 CPU 空转改用 LongAdder(分散热点)或退避策略(指数退避)。
单变量限制无法保证多个变量的原子性合并变量(封装为对象)或使用锁。

5. CAS vs 锁机制
维度CASsynchronized/Lock
锁类型无锁(乐观锁)悲观锁
性能高(无上下文切换)低(锁竞争时性能差)
适用场景简单原子操作、低竞争复杂逻辑、高竞争
编程复杂度需处理 ABA 问题和自旋简单(自动释放锁)

6. 实战代码示例
  1. AtomicInteger 自增

    AtomicInteger count = new AtomicInteger(0);
    count.incrementAndGet(); // 底层通过 CAS 实现
    
  2. 解决 ABA 问题

    AtomicStampedReference<String> ref = new AtomicStampedReference<>("A", 0);
    int stamp = ref.getStamp();
    ref.compareAndSet("A", "B", stamp, stamp + 1); // 更新值并递增版本号
    
  3. 手写自旋锁

    public class SpinLock {private AtomicReference<Thread> owner = new AtomicReference<>();public void lock() {Thread current = Thread.currentThread();while (!owner.compareAndSet(null, current)) {} // CAS 自旋}public void unlock() {owner.compareAndSet(Thread.currentThread(), null);}
    }
    

7. 最佳实践
  1. 优先使用原子类:如 AtomicInteger 替代 synchronized 计数器。
  2. 避免长时间自旋:设置最大重试次数或改用锁。
  3. 高竞争场景优化:使用 LongAdder 代替 AtomicLong
  4. 敏感数据加版本号:如订单状态变更使用 AtomicStampedReference

总结

  • CAS 是 JUC 的基石:通过无锁化实现高效并发,但需处理 ABA 问题和自旋开销。
  • 适用场景:简单原子操作(计数器、标志位)、低竞争环境。
  • 慎用场景:复杂多变量操作、高竞争环境(改用锁或 LongAdder)。
http://www.xdnf.cn/news/8371.html

相关文章:

  • 文章记单词 | 第115篇(六级)
  • upload-labs通关笔记-第19关文件上传之条件竞争
  • EtherNet IP到modbus TCP网关完成AGV系统的安全解决方案及应用
  • 认知偏差:你的思维如何在工作中给你设置障碍以及如何克服它们
  • 基于微信小程序的高校校园微活动管理系统设计与实现(源码+定制+开发)高校微信小程序校园活动发布与互动平台开发 面向大学生群体的校园活动移动平台设计与实现
  • Servlet的继承关系和生命周期
  • 黑马点评-实现分布式锁
  • dify多实例部署,一台机器部署多个dify实例
  • 日语学习-日语知识点小记-构建基础-JLPT-N4阶段(28):ばかり
  • CASIA-HWDB的gnt转换为png图片
  • R语言学习--Day07--T分布与T检验
  • word设置如“第xx页 共xx页”格式的页码
  • OPC Client第5讲(wxwidgets):初始界面的事件处理;按照配置文件初始化界面的内容
  • 【Django DRF】一篇文章总结Django DRF框架
  • 鸿蒙Ability对比Android的Fragment
  • uniapp编译小程序,不支持:class语法
  • 机器学习第二十五讲:TensorFlow → 乐高式搭建深度学习模型
  • kafka吞吐量提升总结
  • halcon 连接相机
  • 消息队列RabbitMQ与AMQP协议详解
  • oracle数据库生成awr报告,排查数据库服务器CPU100%,系统卡顿,慢sql,根据sqlid查询关键信息,如会话SID,客户端机器名
  • 从零搭建SpringBoot Web单体项目3、SpringBoot 核心组件深度解析
  • leetcode hot100:十三、解题思路大全:多维动态规划(不同路径、最小路径和、最长回文子串、 最长公共子序列、编辑距离)
  • 微信小程序用<web-view 嵌入h5网页,改了h5网页后,可能是缓存的原因,小程序上看还是原来的,怎么处理
  • 【MySQL成神之路】MySQL索引相关介绍
  • 应届本科生简历制作指南
  • MySQL数据 在 磁盘上是什么样子的
  • DiagramJS设计原理解读(二)
  • CUDA 加速的基础线性代数库cuBLAS
  • Issac Lab安装