JUC9. AtomicInteger源码
Posted mussessein
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JUC9. AtomicInteger源码相关的知识,希望对你有一定的参考价值。
首先要知道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);
- 首先创建AtomicInteger对象,值会存放在
value
属性中;
// 构造器
public AtomicInteger(int initialValue) {
value = initialValue;
}
- 其次调用
getAndAdd
方法
// 调用getAndAdd方法
private static final Unsafe unsafe = Unsafe.getUnsafe();
public final int getAndAdd(int delta) {
return unsafe.getAndAddInt(this, valueOffset, delta);
}
-
此方法会调用Unsafe类下的多个Native方法
getIntVolatile
和compareAndSwapInt
都是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;
以上是关于JUC9. AtomicInteger源码的主要内容,如果未能解决你的问题,请参考以下文章