AtomicInteger
AtomicInteger
、AtomicLong
、及 AtomicReference
的实现类似,这里以
AtomicInteger
为例。
成员变量
AtomicInteger
类的整体结构如下:
public class AtomicInteger extends Number implements java.io.Serializable {
private static final long serialVersionUID = 6214790243416807050L;
// 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; // ③
//...
}
要点说明如下:
- ① 处调用
Unsafe.getUnsafe
获取Unsafe
实例,该方法在 JUC 中将多次出现 - ② 处获取了 ③ 中定义的
value
字段对应的偏移量,后续调用Unsafe
方法时使用 - ③ 中定义了保存数据的
value
字段,注意它声明的是volatile
我们知道 Unsafe::compareAndSwapInt
方法是保证了有序性与可见性的,那么
value
为什么还要声明成 volatile
?这里因为除了 CAS 相关的方法,
AtomicInteger
还提供了诸如 get/set
方法,这些方法需要变量是 volatile
才能保证有序性与可见性。
getAndSet
getAndSet
用于获取旧的值,并设置成新的值,要注意这个方法在执行时会“自旋”,即轮询直到设置成功。源码如下:
public final int getAndSet(int newValue) {
return unsafe.getAndSetInt(this, valueOffset, newValue);
}
其中 unsafe.getAndSetInt
的实现如下:
public final int getAndSetInt(Object o, long offset, int newValue) {
int v;
do {
v = getIntVolatile(o, offset);
} while (!compareAndSwapInt(o, offset, v, newValue));
return v;
}
这里用 getIntVolatile
保证读取的是最新的值,之后用 compareAndSwapInt
来替换成新的值。这里的自旋+获取旧值+设置新值,也是 CAS 的最典型的使用方式。
compareAndSet
compareAndSet
只是简单封装了 unsafe.compareAndSwapInt
,如果当前值等于expect
,将值设置为新值 update
。
public final boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
lazySet
这个方法是 unsafe.putOrderedInt
的封装,在 Unsafe 一章中说过,它保证有序性,但不保证可见性(修改立即对其它线程可见),因此性能更高。
public final void lazySet(int newValue) {
unsafe.putOrderedInt(this, valueOffset, newValue);
}
weakCompareAndSet
这是一个预留的方法,对它的预期是可能因为示知原因而失败,且不保证有序性。不过看到当前的实现与 compareAndSet
一模一样。
/**
* <p><a href="package-summary.html#weakCompareAndSet">May fail
* spuriously and does not provide ordering guarantees</a>, so is
* only rarely an appropriate alternative to {@code compareAndSet}.
*/
public final boolean weakCompareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
VMSupportsCS8
AtomicLong
中还有一个特殊的变量和方法,用来判断当前 JVM 是否支持 8 字节(long
型)的 CAS 操作,这个方法在 Updater 中会用到。
private static native boolean VMSupportsCS8();
static final boolean VM_SUPPORTS_LONG_CAS = VMSupportsCS8();