概述
AtomicLong 是一个 Java concurrent 包提供的一个原子类,通过这个类可以对 Long 进行一些原子操作。这个类的源码比较简单,主要是依赖于 sun.misc.Unsafe 提供的一些 native 方法保证操作的原子性。基本操作和方法与AtomicInteger类似,大家可以参考之前的AtomicInteger的文章
继承关系
public class AtomicLong extends Number implements java.io.Serializable
成员属性
// setup to use Unsafe.compareAndSwapLong for updates
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long valueOffset;
private volatile long value;
/**
* Records whether the underlying JVM supports lockless
* compareAndSwap for longs. While the Unsafe.compareAndSwapLong
* method works in either case, some constructions should be
* handled at Java level to avoid locking user-visible locks.
*/
static final boolean VM_SUPPORTS_LONG_CAS = VMSupportsCS8();
/**
* Returns whether underlying JVM supports lockless CompareAndSet
* for longs. Called only once and cached in VM_SUPPORTS_LONG_CAS.
*/
private static native boolean VMSupportsCS8();
记录底层JVM是否支持longs的无锁compareAndSwap。 虽然Unsafe.compareAndSwapLong方法在任何一种情况下都可以工作, 但是应该在Java级别处理一些构造以避免锁定用户可见的锁。而VMSupportsCS8() 方法返回底层JVM是否支持longs的无锁CompareAndSet。 仅调用一次并缓存在VM_SUPPORTS_LONG_CAS中
静态代码块
static {
try {
valueOffset = unsafe.objectFieldOffset
(AtomicLong.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
}
基本方法
与AtomicInteger类似,只是在调用unsafe对象的方法时,调用compareAndSwapLong() 方法,例如
public final boolean compareAndSet(long expect, long update) {
return unsafe.compareAndSwapLong(this, valueOffset, expect, update);
}
该方法时基于CAS
其CAS源码核心代码为:
|
1
2
3
4
5
6
7
8
9
|
`int` `compare_and_swap (``int``* reg,` `int` `oldval,` `int` `newval)`
`{`
`ATOMIC();`
`int` `old_reg_val = *reg;`
`if` `(old_reg_val == oldval)`
`*reg = newval;`
`END_ATOMIC();`
`return` `old_reg_val;`
`}`
|
虚拟机指令为:
|
1
2
3
4
|
`mov` `0xc``(%r11),%eax ; Load`
`mov %eax,%r8d`
`inc %r8d ; Increment`
`lock cmpxchg %r8d,``0xc``(%r11) ; Compare and exchange`
|
因为CAS是基于乐观锁的,也就是说当写入的时候,如果寄存器旧值已经不等于现值,说明有其他CPU在修改,那就继续尝试。所以这就保证了操作的原子性。