简介
AtomicInteger 主要操作 int 类型的数据,通过调用 Unsafe 类的 CAS 等方法实现原子操作
成员变量
- value ,保存程序设定的值,用 volatile 修饰,保证可见性
- valueOffset,value 变量对应的内存偏移地址
// 获取 Unsafe 实例private static final Unsafe unsafe = Unsafe.getUnsafe();// value 字段的偏移量,相对于 AtomicInteger 对应实例的首地址的偏移量private static final long valueOffset;static {try {// 获取 value 的偏移量valueOffset = unsafe.objectFieldOffset(AtomicInteger.class.getDeclaredField("value"));} catch (Exception ex) { throw new Error(ex); }}// 保存对应的值,保持可见性private volatile int value;
构造方法
- 设置 volatile 修饰的 value 的值
public AtomicInteger(int initialValue) {value = initialValue;}/*** Creates a new AtomicInteger with initial value {@code 0}.*/public AtomicInteger() {}
成员方法
getAndSet
将 value 设定为 newValue
public final int getAndSet(int newValue) {return unsafe.getAndSetInt(this, valueOffset, newValue);}// Unsafe 中的方法public final int getAndSetInt(Object var1, long var2, int var4) {int var5;do {var5 = this.getIntVolatile(var1, var2);} while(!this.compareAndSwapInt(var1, var2, var5, var4));return var5;}
compareAndSet
public final boolean compareAndSet(int expect, int update) {return unsafe.compareAndSwapInt(this, valueOffset, expect, update);}// Unsafe 中的方法public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);
通过比较 valueOffset 处的值是否与 expect 相等,若相等,将 valueOffset 偏移量处的值更新为 update,否则不处理;
更新成功返回 true,更新失败返回 false。
getAndIncrement,getAndDecrement
public final int getAndIncrement() {return unsafe.getAndAddInt(this, valueOffset, 1);}public final int getAndDecrement() {return unsafe.getAndAddInt(this, valueOffset, -1);}// Unsafe 中的方法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;}public native int getIntVolatile(Object var1, long var2);
将 valueOffset 对应的值加 1/减 1,注意这里有个循环的过程,直到更新成功。
返回更新前的 value
incrementAndGet
public final int incrementAndGet() {return unsafe.getAndAddInt(this, valueOffset, 1) + 1;}
返回更新后的 value
CAS 问题
- 过度消耗 CPU
自旋 CAS 如果长时间不成功,会给 CPU 带来非常大的执行开销
- ABA 问题

Java 提供了 AtomicStampedReference 工具类,通过为引用建立类似版本号(stamp)的方式,来保证 CAS 的正确性。
