什么是 CAS

335 阅读2分钟

一、CAS 的概念:比较并交换

CAS(Compare and Swap)指比较并交换。CAS 算法 CAS(V,E,N)包含了 3 个参数,V 表示要更新的变量,E 表示预期的值,N 表示新值。在且仅在 V 值等于 E 时,才会将 V 值设为 N ,如果 V 值和 E 值不同,则说明已经有其他线程做了更新,当前线程什么都不做。最后,CAS 返回当前 V 的真实值。

二、CAS 的特性:乐观锁

CAS 操作采用了乐观锁的思想,总是任务自己可以成功完成操作。在有多个线程同时使用 CAS 操作一遍变量时,只有一个会胜出并成功更新,其余均会失败。失败 线程不会被挂起,仅被告知失败,并且运行在此尝试,当然,也允许失败的线程继续操作,基于这样的原理,CAS 操作即使没有锁,也可以发现其他线程对当前线程的干扰,并进行恰当的处理。

三、CAS 自旋等待

在 JDK 的原子包 java.util.concurrent.atomic 里面提供了一组原子类,这些原子类的基本特性就是在多线程环境下,在有多个线程同时执行这些类的实例包含的方法时,会有排他性。其内部便是基于 CAS 算法实现的,即在某个线程进入方法中执行其中的指令时,不会被其他线程打断;而别的线程就像自旋锁一样,一直等到该方法执行完成才由 JVM 从等待的队列中选择另一个线程进入。

相对于 synchronized 阻塞算法,CAS 是非阻塞算法的一种常见实现。由于 CPU 上下文切换比 CPU 指令集的操作更加耗时,所以 CAS 的自旋操作在性能上有了很多的提升。JDK 具体的实现源码如下:

public class AtomicInteger extends Number implements java.io.Serializable {
    
    private voliatile int value;
    
    public final int get(){
        return value;
    }
    
    public final int getAndIncrement(){
        for(;;){ // CAS 自旋,一直尝试,直到成功
            int current = get();
            int next = current + 1;
            if(compareAndSet(current,next)){
                return current;
            }
        }
    }
    
    
    public final boolean weakCompareAndSet(int expect, int update) {
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }


}

在以上代码中 getAndIncrement 采用了 CAS 的操作,每次都从内存中读取数据然后将此数据和加 1 后的结果进行 CAS 操作,如果成功,则返回结果,否则重试直到成功为止。

知乎搜索:搬砖小李哥

image.png

微信公众号关注:peki

image.png

image.png