目录

Life in Flow

知不知,尚矣;不知知,病矣。
不知不知,殆矣。

X

CAS

CAS 简介

 compare and swap
 一种思想、一种用来实现线程安全的算法。
 同时也是一种 CPU 指令: compare and swap(比较和交换),一种不会被打断的操作组合。

实现思路
 我认为 V 的值应该是 A,如果是的话我就把它修改成 B,如果不是 A(说明被别人修改过),那我就不修改了,避免多人同时修改导致出错。
 CAS 有三个操作数:内存值 V、预期值 A、要修改的值 B,当且仅当预期值 A 和内存值 V 相同时,才将内存值修改为 B,否则什么都不做。最后返回现在的值。
CAS

1* CPU 的特殊指令保证了原子性

CAS 等价代码(Java)

 1/**
 2 * 描述:     Java 代码 模拟CAS操作,等价代码
 3 */
 4public class SimulatedCAS {
 5    private volatile int value;
 6    
 7    //整个方法作用相当于 CPU 的一条指令(CAS 指令)
 8    public synchronized int compareAndSwap(int expectedValue, int newValue) {
 9        int oldValue = value;
10        if (oldValue == expectedValue) {//compare
11            value = newValue;//swap
12        }
13        return oldValue;
14    }
15}

案例演示

 断掉调试,观察不同线程运行情况。

 1import java.util.concurrent.ConcurrentHashMap;
 2import java.util.concurrent.atomic.AtomicInteger;
 3import java.util.concurrent.atomic.AtomicIntegerArray;
 4
 5/**
 6 * 描述:     模拟CAS操作,等价代码
 7 */
 8public class TwoThreadsCompetition implements Runnable {
 9
10    private volatile int value;
11
12    public synchronized int compareAndSwap(int expectedValue, int newValue) {
13        int oldValue = value;
14        if (oldValue == expectedValue) {
15            value = newValue;
16        }
17        return oldValue;
18    }
19
20    @Override
21    public void run() {
22        compareAndSwap(0, 1);
23    }
24
25    public static void main(String[] args) throws InterruptedException {
26        TwoThreadsCompetition r = new TwoThreadsCompetition();
27        r.value = 0;
28        Thread t1 = new Thread(r,"Thread 1");
29        Thread t2 = new Thread(r,"Thread 2");
30        t1.start();
31        t2.start();
32        t1.join();
33        t2.join();
34        System.out.println(r.value);
35    }
36}

应用场景

  • 乐观锁
  • 并发容器
  • 原子类
1* AtomicInteger 加载 Unsafe 工具,用来直接操作内存数据。
2* 用 Unsafe 来实现底层操作(Unsafe是CAS的核心类,Java无法直接访问底层操作系统,而是通过本地方法native 来访问。尽管如此,JVM还是开了一个后门,JDK中有一个类Unsafe,它提供了硬件级别的原子操作。)
3* 用 volatile 修饰 value 字段,保证可见性
4* getAndAddInt() 方法分析

实现原理

 Unsafe 类中的 compareAndSwapInt()

1* 方法中先想办法拿到变量 value 在内存中的地址。
2* 通过Atomic:cmpxchg 实现原子性的比较和替换,其中参数x 是即将更新的值,参数 e 是原内存的值。至此,最终完成了 CAS 的全过程。

缺点

  • ABA 问题。(解决办法使用增加版本号)
  • 自旋时间过长

作者:Soulboy