提供對 long 類型的原子操作。32 位 JVM 下 long/double 非原子(拆兩次 32 位操作),AtomicLong 保證原子性。
AtomicLong()、AtomicLong(long initialValue)get()、set(v)、lazySet(v)getAndIncrement()、incrementAndGet()、getAndDecrement()、decrementAndGet()getAndAdd(delta)、addAndGet(delta)compareAndSet(expect, update)、weakCompareAndSet(expect, update)getAndSet(v)、類型轉換方法(intValue() 等)。public class AtomicLong extends Number implements Serializable {
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long valueOffset;
private volatile long value; // volatile 保證可見性
public final long incrementAndGet() {
for (;;) {
long current = get(); // 讀取最新值
long next = current + 1; // 計算新值
if (compareAndSet(current, next)) return next; // CAS 更新
}
}
public final boolean compareAndSet(long expect, long update) {
return unsafe.compareAndSwapLong(this, valueOffset, expect, update);
}
}
原理:volatile 保證線程間可見性;Unsafe.compareAndSwapLong 硬件級 CAS 指令保證「讀-改-寫」原子性,無需鎖。
// LongTest.java
AtomicLong m = new AtomicLong();
m.set(0x0123456789ABCDEFL);
System.out.printf("get(): 0x%016X\n", m.get());
System.out.printf("getAndDecrement(): 0x%016X\n", m.getAndDecrement());
System.out.printf("decrementAndGet(): 0x%016X\n", m.decrementAndGet());
System.out.printf("getAndIncrement(): 0x%016X\n", m.getAndIncrement());
System.out.printf("incrementAndGet(): 0x%016X\n", m.incrementAndGet());
System.out.printf("addAndGet(0x10): 0x%016X\n", m.addAndGet(0x10));
System.out.printf("getAndAdd(0x10): 0x%016X\n", m.getAndAdd(0x10));
System.out.printf("compareAndSet(0x12345679L, 0xFEDCBA9876543210L): %s\n", m.compareAndSet(0x12345679L, 0xFEDCBA9876543210L));
get(): 0x0123456789ABCDEF getAndDecrement(): 0x0123456789ABCDEF decrementAndGet(): 0x0123456789ABCDED getAndIncrement(): 0x0123456789ABCDED incrementAndGet(): 0x0123456789ABCDEF addAndGet(0x10): 0x0123456789ABCDFF compareAndSet(...): false // 期望值不匹配,更新失敗