JDK源码解析之AtomicInteger及CAS

前言:

    JDK中的锁大致可以分为两类:Synchronized和CAS。

    CAS的使用中,有直接使用的,比如AtomicInteger;有间接使用的比如ReentrantLock。

    本文就说一下直接使用CAS的AtomicInteger类,看其是如何直接使用的

1.CAS

    CAS是Compare and Swap(比较并交换)的简称

    CAS有三个操作数:内存值V、旧的预期值A、要修改的值B,当且仅当预期值A与内存值V相等时,则将内存值修改为B并返回true,否则返回false。

    

2.Unsafe

    JDK中sun.misc包下有一个Unsafe类,里面的方法基本都是native类型的,这些方法提供了硬件级别的原子操作

public final native boolean compareAndSwapObject(Object var1, long var2, Object var4, Object var5);

public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);

public final native boolean compareAndSwapLong(Object var1, long var2, long var4, long var6);

    这些方法,在JDK内部可以直接使用(注意:我们个人写的类无法直接调用这些方法),所有的CAS操作基本都是通过Unsafe的这些compareAndSwap方法实现的

3.AtomicInteger对CAS的运用

    AtomicInteger作为Integer的并发安全类,我们可以直接使用该类在多线程环境下进行Integer的相关操作

    1)常规操作

AtomicInteger atomicInteger = new AtomicInteger();

// 设定初始值
atomicInteger.set(10);

// 自增,类似于++i
int i = atomicInteger.incrementAndGet();// i=11

int i1 = atomicInteger.addAndGet(2);// i=13

// 类似于i++
int andIncrement = atomicInteger.getAndIncrement();// andIncrement=13

// 类似于--i
int i2 = atomicInteger.decrementAndGet();// i2=13

// 获取当前值
int i3 = atomicInteger.get();

    2)AtomicInteger与CAS

public class AtomicInteger extends Number implements java.io.Serializable {
    private static final long serialVersionUID = 6214790243416807050L;

    // 1.创建Unsafe的引用
    private static final Unsafe unsafe = Unsafe.getUnsafe();
    // 2.初始值,使用volatile类型,保证可见性
    private volatile int value;

    // 以下是两种构造方法
    public AtomicInteger(int initialValue) {
        value = initialValue;
    }
    public AtomicInteger() {
    }

    AtomicInteger创建了关于Unsafe的引用作为成员变量

    3)AtomicInteger.incrementAndGet()分析

public final int incrementAndGet() {
    // 直接调用unsafe.getAndAddInt
    return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
}

// unsafe.getAndAddInt
public final int getAndAddInt(Object var1, long var2, int var4) {
    int var5;
    do {
        // 获取当前新值,不停的获取最新值,并在当前最新值上加1
        var5 = this.getIntVolatile(var1, var2);
        
        // this.compareAndSwapInt()方法也是native类型的
        // 如果该方法返回false,也就是设置失败的情况下,则一直循环,直到设置成功
    } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));

    return var5;
}

    总计:可以看出AtomicInteger的操作就是在一个while循环中,不停的获取当前最新值N,然后再设置value值为N+1,使用Unsafe.compareAndSwapInt()方法一直到设置成功为止

    其他方法也与该方法类似,不再分析

    

发布了124 篇原创文章 · 获赞 126 · 访问量 13万+

猜你喜欢

转载自blog.csdn.net/qq_26323323/article/details/86496861
今日推荐