码迷,mamicode.com
首页 > 其他好文 > 详细

【JUC】9. AtomicInteger源码

时间:2020-04-05 09:40:41      阅读:58      评论:0      收藏:0      [点我收藏+]

标签:integer源码   api   方法   dad   源码   public   nat   long   off   

首先要知道CAS

CAS

Compare and Swap,即比较再交换;

区别于synchronouse同步锁的一种乐观锁(是一种无锁算法)

CAS有3个操作数,

  • 内存地址,以直接从内存中获取旧值;
  • 旧的预期值A,代码中的旧值;
  • 要修改的新值B

当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做;

CAS是CPU级别的指令操作,上述操作是一步原子操作;

缺陷

ABA问题

有可能value被改了,又被改回来了,那么CAS算法是无法发现value已经被修改过了,误认为没有被修改;

AtomicInteger

private volatile int value;
private static final long valueOffset;
// 通过unsafe对象,来进行native操作
private static final Unsafe unsafe = Unsafe.getUnsafe();

两个重要属性:

  • value:就是创建此对象的值
  • valueOffset

valueOffset

就是说:AtomicInteger对象,在创建完成之后,在内存中分配一片内存,其中此对象的每个属性相对于这片内存的偏移量就已经确定了;

valueOffset就是AtomicInteger对象的value属性在内存中的偏移量;

通过下面的Unsafe类的native方法,直接从内存中获取value的值;

private static final long valueOffset;
static {
    try {
        valueOffset = unsafe.objectFieldOffset
            (AtomicInteger.class.getDeclaredField("value"));
    } catch (Exception ex) { throw new Error(ex); }
}

getAndAdd方法

我们要执行下面一系列操作时:

AtomicInteger i = new AtomicInteger(0);
int original =i.getAndAdd(3);

  1. 首先创建AtomicInteger对象,值会存放在value属性中;
// 构造器
public AtomicInteger(int initialValue) {
    value = initialValue;
}
  1. 其次调用getAndAdd方法
// 调用getAndAdd方法
private static final Unsafe unsafe = Unsafe.getUnsafe();
public final int getAndAdd(int delta) {
    return unsafe.getAndAddInt(this, valueOffset, delta);
}
  1. 此方法会调用Unsafe类下的多个Native方法

    getIntVolatilecompareAndSwapInt都是Unsafe类下的native方法;

    getIntVolatile:就是CAS中的根据内存地址,直接在内存级别获取当前旧值;

    compareAndSwapInt:就是CAS的比较修改的操作,修改成功,返回true,那么跳出循环;修改失败,继续尝试获取内存值,进行修改;

// 再调用Unsafe类下的getAndAddInt方法
public final int getAndAddInt(Object var1, long var2, int var4) {
    int var5;
    // CAS操作
    do {
        /**
         * var1:我们创建的AtomicInteger对象
         * var2:valueOffset
         * 就是找到此对象下,value属性在内存中的偏移量,在内存级别直接拿到value的值
         */
        var5 = this.getIntVolatile(var1, var2); 
    } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));
	// 返回旧值
    return var5;
}

getAndIncrement方法

getAndAdd类似

同样是调用unsafe对象下的unsafe.getAndAddInt(this, valueOffset, 1)

只不过delta直接传值为1;

【JUC】9. AtomicInteger源码

标签:integer源码   api   方法   dad   源码   public   nat   long   off   

原文地址:https://www.cnblogs.com/mussessein/p/12635570.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!