HelloCoder HelloCoder
首页
《Java小白求职之路》
《小白学Java》
计算机毕设
  • 一些免费计算机资源
  • 脚手架工具
  • 《从0到1学习Java多线程》
  • 《从0到1搭建服务器》
  • 《可观测和监控》
随笔
关于作者
首页
《Java小白求职之路》
《小白学Java》
计算机毕设
  • 一些免费计算机资源
  • 脚手架工具
  • 《从0到1学习Java多线程》
  • 《从0到1搭建服务器》
  • 《可观测和监控》
随笔
关于作者
  • 《LearnJavaToFindAJob》

    • 导读

    • 【初级】6~12k档

    • 【中级】12k-26k档

      • JVM进阶

      • Java进阶

        • ConcurrentHashMap面试题
        • CopyOnWriteArrayList的实现原理
        • HashMap的put过程是怎么样的?
        • IO模型有哪些?
        • Synchronized相关
        • ThreadLocal的原理
        • synchronized锁升级
        • valueOf、(String)强转有什么区别?
        • 为什么在lambda中使用的局部变量必须是final或有效final
        • 你知道如何更新缓存吗?如何保证缓存和数据库双写一致性?
        • 八股文之ReentrantLock
        • 分布式事务
        • 如何保障生产端消息投递成功?
        • 如何手动触发全量回收垃圾,如何立即触发垃圾回收
        • 数据库连接池为什么要使用ThreadLocal?
        • 线程池中多余的线程是如何回收的
        • 谈谈你对AQS的理解
        • 谈谈你对CAS的理解
        • util.concurrent的理解
        • 高并发下如何保证接口的幂等性?
      • MySQL

      • 中间件

      • 算法

      • 高阶

    • 【高级】26k+档

    • 大厂面试题

    • 求职建议

    • 面经

  • LearnJavaToFindAJob
  • 【中级】12k-26k档
  • Java进阶
#CAS #谈谈你对 #理解
码农阿雨
2022-06-02
目录

谈谈你对CAS的理解

# CAS(Compare And Swap)

# 一、CAS是什么?

CAS是CPU的原子指令,实现无锁并发的核心技术。它的工作模式是:

// 逻辑伪代码(不是真实实现)
boolean compareAndSwap(address, expectedValue, newValue) {
    if (*address == expectedValue) {  // 1. 比较:当前值是否等于预期值
        *address = newValue;           // 2. 交换:如果是,更新为新值
        return true;                    // 3. 成功返回true
    }
    return false;                       // 4. 失败返回false
}

一句话概括:"我认为现在的值是A,如果是,就改成B,不是就不改"

# 二、为什么需要CAS?

# 传统锁的问题

public class CounterProblem {
    private int count = 0;
    
    // 方案1:synchronized(悲观锁)
    public synchronized void increment() {
        count++;  // 即使没有竞争,也要加锁
    }
    
    // 方案2:CAS(乐观锁)
    private AtomicInteger atomicCount = new AtomicInteger(0);
    public void increment() {
        atomicCount.incrementAndGet();  // 无锁,失败重试
    }
}

# 对比

维度 synchronized CAS
思想 悲观(先锁再干) 乐观(先干不行再重试)
开销 线程挂起/唤醒(重量级) 自旋(轻量级)
竞争激烈 好(线程让出CPU) 差(CPU空转)
竞争不激烈 差(不必要切换) 好(无上下文切换)

# 三、CAS的三个核心操作数

public class CASComponents {
    // 1. 内存地址 V(要操作的位置)
    // 2. 预期值 A(我认为现在是什么)
    // 3. 新值 B(我想改成什么)
    
    private AtomicInteger value = new AtomicInteger(0);
    
    public void increment() {
        // 底层调用 Unsafe.compareAndSwapInt
        int expect;
        int update;
        do {
            expect = value.get();           // 读取当前值
            update = expect + 1;             // 计算新值
        } while (!value.compareAndSet(expect, update));  // CAS尝试
    }
}

# 四、CAS在Java中的实现

# 1. Unsafe类 - CAS的底层入口

public final class Unsafe {
    // native方法,直接调用CPU指令
    public final native boolean compareAndSwapObject(
        Object obj, long offset, Object expect, Object update);
    
    public final native boolean compareAndSwapInt(
        Object obj, long offset, int expect, int update);
    
    public final native boolean compareAndSwapLong(
        Object obj, long offset, long expect, long update);
}

# 2. CPU指令支持

; x86架构的CMPXCHG指令
lock cmpxchg [addr], eax  ; 原子的比较并交换
; lock前缀保证原子性
; eax寄存器存预期值
; 如果相等,ZF=1,目标操作数←源操作数
; 如果不相等,ZF=0,累加器←目标操作数

# 五、CAS的经典应用

# 1. 原子类(AtomicInteger等)

public class AtomicIntegerDemo {
    private AtomicInteger counter = new AtomicInteger(0);
    
    public int increment() {
        // 实现原理:CAS自旋
        return counter.incrementAndGet();
    }
    
    public int add(int delta) {
        // 典型CAS模式
        int current, next;
        do {
            current = counter.get();
            next = current + delta;
        } while (!counter.compareAndSet(current, next));
        return next;
    }
}

# 2. 并发容器(ConcurrentHashMap)

// ConcurrentHashMap中的CAS使用
static final <K,V> Node<K,V> tabAt(Node<K,V>[] tab, int i) {
    return (Node<K,V>)U.getObjectAcquire(tab, ((long)i << ASHIFT) + ABASE);
}

static final <K,V> boolean casTabAt(Node<K,V>[] tab, int i,
                                    Node<K,V> c, Node<K,V> v) {
    // CAS更新数组元素,无锁并发
    return U.compareAndSetObject(tab, ((long)i << ASHIFT) + ABASE, c, v);
}

# 3. 锁的实现(AQS)

// AbstractQueuedSynchronizer中的CAS
private static final long stateOffset;

static {
    try {
        stateOffset = unsafe.objectFieldOffset
            (AbstractQueuedSynchronizer.class.getDeclaredField("state"));
    } catch (Exception ex) { throw new Error(ex); }
}

protected final boolean compareAndSetState(int expect, int update) {
    // CAS更新AQS状态
    return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}
阅读全文
×

(为防止恶意爬虫)
扫码或搜索:HelloCoder
发送:290992
即可永久解锁本站全部文章

解锁
#CAS#谈谈你对#理解
上次更新: 2026-03-18 15:32:38
最近更新
01
MySQL支持的锁有哪些
03-18
02
用户态和内核态的区别
03-18
03
Synchronized相关
03-18
更多文章>
Theme by Vdoing | Copyright © 2020-2026 码农阿雨
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式