AtomicInteger原理,CAS 机制,乐观锁,ABA问题

示例
val atomicInteger = AtomicInteger(10)
atomicInteger.decrementAndGet()// atomicInteger-- 
  • 从静态代码块可以看到,在类初始化的时候拿到值的偏移量(获取偏移量后直接操作内存,从内存取值,不通过缓冲区)。在构造函数保存初始值,并且是volatile修饰
public class AtomicInteger extends Number implements java.io.Serializable {
    private static final long serialVersionUID = 6214790243416807050L;

    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
    private static final long VALUE;

    static {
        try {
            VALUE = U.objectFieldOffset
                (AtomicInteger.class.getDeclaredField("value"));
        } catch (ReflectiveOperationException e) {
            throw new Error(e);
        }
    }

    private volatile int value;

    /**
     * Creates a new AtomicInteger with the given initial value.
     *
     * @param initialValue the initial value
     */
    public AtomicInteger(int initialValue) {
        value = initialValue;
    }
  • 查看decrementAndGet源码
public final int decrementAndGet() {
        return U.getAndAddInt(this, VALUE, -1) - 1;
    }
  • U是sun.misc.Unsafe类里面的,找到Unsafe里面的getAndAddInt
public final int getAndAddInt(Object var1, long var2, int var4) {
        int var5;
        do {
            var5 = this.getIntVolatile(var1, var2);
        } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));

        return var5;
    }
  • var1就是atomic对象,var2就是偏移量,var4就是要做的减1。var5是通过对象起始地址偏移VALUE的距离,拿到9(示例代码设置的9),是从主内存拿的。
  • compareAndSwapInt就是 CAS 机制
  • 首先计算var5 + var4的值,然后存储一份,然后再通过var1, var2在内存中拿到atomic的值,对比拿到的和var5 + var4的值是否相等,如果相等就允许var5减一(var5与var5 + var4交换)然后返回,如果不等就一直循环判断。
  • 在单线程中没有意义反而变复杂了
  • 假如有AB两个线程,A线程在执行var5 + var4的操作之后时间片段用完了,切换到B线程,B线程已经走完了所有流程,值已经被修改为9。再切换到A线程的时候接着执行通过var1, var2在内存中拿到atomic的值,对比拿到的和var5 + var4的值是否相等就会发现不相等了,因为已经被修改了,然后重新执行do循环里面的操作,重新在内存取值,取到9,然后判断是相等的,也就跳出循环了。
  • 对比拿到的和var5 + var4的值是否相等和对var5赋值是有CPU保证操作是原子性的
  • 这也是乐观锁
  • 没有通过复杂的机制来阻塞线程,并且达到目的,比加锁的代码效率提高很多
  • 但是只适合少量并发中使用,高并发中会导致CPU占用率高。
  • 这种乐观锁(无锁)机制还有一个ABA问题。假如操作的是引用类型,在AB两个线程中,一开始对象是a,在循环中间把对象换成了b,然后又换成了a,对比结果还是a,但是其实中间做了很多其他事情,在并发中可能会导致严重问题


    CAS.jpg

推荐阅读更多精彩内容