目录
一、AtomicInteger的基本用法
1、创建AtomicInteger
2、常用方法说明
2.1、自增方法
2.2、自减方法
2.3、原子性的更新值
2.4、其他方法
3、AtomicInteger内幕
3.1、compareAndSwapInt 源码分析
3.2、getAndAddInt 自旋方法
四、总结
AtomicInteger与int的引用类型Integer继承Number类一样,AtomicInteger也是Number类的一个子类,除此之外,AtomicInteger还提供了很多原子性的操作方法。在AtomicInteger的内部有一个被volatile关键字修饰的成员变量value,实际上,AtomicInteger所提供的所有方法主要都是针对该变量value进行的操作。
AtomicInteger类提供了AtomicInteger() 和 AtomicInteger(int initialValue) 两个构造方法,有参数的可以指定一个初始值,无参的构造方法默认值为0,相当于 AtomicInteger( 0 )。
public static void main(String[] args) {
AtomicInteger count = new AtomicInteger(2);
// 先返回旧值,然后自增
System.out.println("返回值:" + count.getAndIncrement());
//返回当前值
System.out.println("当前值:" + count.get());
//直接返回自增后的结果
System.out.println("返回值:" + count.incrementAndGet());
System.out.println("当前值:" + count.get());
}
public static void main(String[] args) {
AtomicInteger count = new AtomicInteger(2);
// 先返回旧值,然后自减
System.out.println("返回值:" + count.getAndDecrement());
//返回当前值
System.out.println("当前值:" + count.get());
//直接返回自减后的结果
System.out.println("返回值:" + count.decrementAndGet());
System.out.println("当前值:" + count.get());
}
看看 AtomicInteger 类的内部原理,以更加深入地了解 AtomicInteger 的内幕。
// setup to use Unsafe.compareAndSwapInt for updates
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long valueOffset;
static {
try {
valueOffset = unsafe.objectFieldOffset
(AtomicInteger.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
}
private volatile int value;
上面是 AtomicInteger 类的代码片段,我们看到 类中 主要有 一个量静态变量 Unsafe unsaf 和 volatile 修饰 的 int value 变量。AtomicInteger 内部也只要是通过Unsafe 类操作 value 变量来完成原子操作的。
我们看下在 AtomicInteger 类内部的 compareAndSet 方法内部调用的就是 Unsafe 类的 compareAndSwapInt 方法。
public final boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
在 《CAS 原理》 一章中介绍过 CAS 操作包含三个三个参数分别为:内存值V、旧的预期值A、要修改的新值B,当且仅当预期值A与内存值V相等时,将内存值V修改为B,否则什么都不需要做。compareAndSwapInt 方法是一个 native 方法,其提供了CAS(Compare AndSwap)算法的实现,AtomicInteger类中的原子性方法几乎都借助于该方法实现。
由于compareAndSwapInt方法的乐观锁特性,会存在对value修改失败的情况,但是有些时候对value的更新必须要成功,比如调用incrementAndGet、addAndGet等方法,本节就来分析一下addAndGet方法的实现。
public final int getAndAddInt(Object var1, long var2, int var4) {
int var5;
do {
var5 = this.getIntVolatile(var1, var2); // 1
} while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4)); // 2
return var5;
}
AtomicInteger 提供了一个原子性的操作,其内部是通过调用 Unsafe 类提供的 native 方法通过 CAS 操作实现的。在某些方法中更是通过 自旋 + CAS 的方式实现的更新操作。