Java

CAS

勤劳的小蜜蜂 · 2月28日 · 2020年

什么是 CAS

概念:
CAS(Compare-and-Swap),即比较并替换,是一种实现并发算法时常用到的技术,Java并发包中的很多类都使用了CAS技术。

举例:
我认为 V的值应该是 A,如果是的话那我就可以把它改成 B,如果不是 A(说明被别人修改过了)
,那我就不修改了,避免多人同时修改导致出错

分析:
CAS有三个操作数:内存值V、预期值A、要修改的值B,当且仅当预期值A和内存值V相同时,才将内存值修改为 B,否则什么都不做。最后返回现在的V值。

案例演示

/**
 * @Author: ye
 * @Date: 2020-02-28 13:53
 * @Description: 模拟 CAS 操作,等价代码
 */
public class TwoThreadsCompetition implements Runnable{
    private volatile int vaule;

    /**
     * 模拟 CAS 操作类
     * @param expectedVaule
     * @param newVaule
     * @return
     */
    public synchronized int compareAndSwap(int expectedVaule, int newVaule) {
        int oldValue = vaule;
        if (oldValue == expectedVaule) {
            vaule = newVaule;
        }
        return oldValue;
    }

    /**
     * 多线程竞争,最后只有一个线程修改成功
     * @param args
     * @throws InterruptedException
     */
    public static void main(String[] args) throws InterruptedException {
        TwoThreadsCompetition twoThreadsCompetition = new TwoThreadsCompetition();
        twoThreadsCompetition.vaule = 0;
        Thread t1 = new Thread(twoThreadsCompetition);
        Thread t2 = new Thread(twoThreadsCompetition);
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println(twoThreadsCompetition.vaule);
    }

    @Override
    public void run() {
        compareAndSwap(0, 1);
    }
}

以AtomicInteger为例,分析在JAVA中是如何利用CAS实现院子操作的?

  • AtmoicInteger 加载 Unsafe 工具,用来直接操作内存数据
  • 用 Unsafe 来实现底层操作
  • 用 volatile 修饰 value 字段,保证可见性

Unsafe 类
Unsafe 是 CAS 的核心类。Java 无法直接访问底层操作系统,而是通过本地(navtive)方法来访问。不过尽管如此,JVM 还是开了一个后门,JDK 中有一个类 Unsafe,它提供了硬件级别的原子操作。

应用场景

  • 乐观锁
  • 并发容器
  • 原子类

缺点

  • ABA 问题
    • CAS 只会比较值是否相等
    • 解决方法:加版本号
  • 自旋时间过长:消耗 CPU 资源