AtomicInteger 源码分析

摘要:

  1. AtomicInteger 是怎么做到线程安全的
  2. AtomicInteger 是怎么实现自增的

TOP 带着问题看源码

  1. AtomicInteger 是怎么做到线程安全的
  2. AtomicInteger 是怎么实现自增的

1. 基本介绍

AtomicInteger 扩展了 Number,适用于基于数字的处理,并提供了如原子递增等,适合一些计数场景

1
2
3
4
5
6
7
8
9
10
11
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;

可以看到 value 是采用 volatile 修饰的,并通过 Unsafe 类获取 value 的偏移量,方便后续使用 CAS 操作

2. 自增 & 自减

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 获取 & 自增
public final int getAndIncrement() {
return unsafe.getAndAddInt(this, valueOffset, 1);
}
// 自增 & 获取
public final int incrementAndGet() {
return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
}
// 获取 & 自减
public final int getAndDecrement() {
return unsafe.getAndAddInt(this, valueOffset, -1);
}
// 自减 & 获取
public final int decrementAndGet() {
return unsafe.getAndAddInt(this, valueOffset, -1) - 1;
}

AtomicInteger 提供了自增/自减的两个场景方法,一个返回旧值,一个返回新增/自减后的。

实际都是通过Unsafe 的 getAndAddInt 方法来实现的,可以看到实际上 getAndAddInt 就是一个 cas + 自旋操作来实现。

1
2
3
4
5
6
7
8
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;
}

回到 TOP 问题1 2 可以看到实际是采用 CAS + 自旋来实现线程安全的自增