简介

AtomicInteger 主要操作 int 类型的数据,通过调用 Unsafe 类的 CAS 等方法实现原子操作

成员变量

  • value ,保存程序设定的值,用 volatile 修饰,保证可见性
  • valueOffset,value 变量对应的内存偏移地址
  1. // 获取 Unsafe 实例
  2. private static final Unsafe unsafe = Unsafe.getUnsafe();
  3. // value 字段的偏移量,相对于 AtomicInteger 对应实例的首地址的偏移量
  4. private static final long valueOffset;
  5. static {
  6. try {
  7. // 获取 value 的偏移量
  8. valueOffset = unsafe.objectFieldOffset
  9. (AtomicInteger.class.getDeclaredField("value"));
  10. } catch (Exception ex) { throw new Error(ex); }
  11. }
  12. // 保存对应的值,保持可见性
  13. private volatile int value;

构造方法

  • 设置 volatile 修饰的 value 的值
  1. public AtomicInteger(int initialValue) {
  2. value = initialValue;
  3. }
  4. /**
  5. * Creates a new AtomicInteger with initial value {@code 0}.
  6. */
  7. public AtomicInteger() {
  8. }

成员方法

getAndSet

将 value 设定为 newValue

  1. public final int getAndSet(int newValue) {
  2. return unsafe.getAndSetInt(this, valueOffset, newValue);
  3. }
  4. // Unsafe 中的方法
  5. public final int getAndSetInt(Object var1, long var2, int var4) {
  6. int var5;
  7. do {
  8. var5 = this.getIntVolatile(var1, var2);
  9. } while(!this.compareAndSwapInt(var1, var2, var5, var4));
  10. return var5;
  11. }

compareAndSet

  1. public final boolean compareAndSet(int expect, int update) {
  2. return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
  3. }
  4. // Unsafe 中的方法
  5. public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);

通过比较 valueOffset 处的值是否与 expect 相等,若相等,将 valueOffset 偏移量处的值更新为 update,否则不处理;

更新成功返回 true,更新失败返回 false。

getAndIncrement,getAndDecrement

  1. public final int getAndIncrement() {
  2. return unsafe.getAndAddInt(this, valueOffset, 1);
  3. }
  4. public final int getAndDecrement() {
  5. return unsafe.getAndAddInt(this, valueOffset, -1);
  6. }
  7. // Unsafe 中的方法
  8. public final int getAndAddInt(Object var1, long var2, int var4) {
  9. int var5;
  10. do {
  11. var5 = this.getIntVolatile(var1, var2);
  12. } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));
  13. return var5;
  14. }
  15. public native int getIntVolatile(Object var1, long var2);

将 valueOffset 对应的值加 1/减 1,注意这里有个循环的过程,直到更新成功。

返回更新前的 value

incrementAndGet

  1. public final int incrementAndGet() {
  2. return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
  3. }

返回更新后的 value

CAS 问题

  • 过度消耗 CPU

自旋 CAS 如果长时间不成功,会给 CPU 带来非常大的执行开销

  • ABA 问题
    AtomicInteger 源码学习 - 图1
    Java 提供了 AtomicStampedReference 工具类,通过为引用建立类似版本号(stamp)的方式,来保证 CAS 的正确性。