我們先來看部分原始碼:
public class AtomicLong extends Number implements java.io.Serializable { private static final long serialVersionUID = 1927816293512124184L; //1.获取Unsafe类实例 private static final Unsafe unsafe = Unsafe.getUnsafe(); //2.存放value的偏移量 private static final long valueOffset; static final boolean VM_SUPPORTS_LONG_CAS = VMSupportsCS8(); //3.用于判断是否支持Long类型无锁CAS private static native boolean VMSupportsCS8(); static { try { //4.获取value在AtomicLong中的偏移量 valueOffset = unsafe.objectFieldOffset (AtomicLong.class.getDeclaredField("value")); } catch (Exception ex) { throw new Error(ex); } } //5.实际变量值 private volatile long value; /** * Creates a new AtomicLong with the given initial value. * * @param initialValue the initial value */ public AtomicLong(long initialValue) { value = initialValue; } ············省略部分代码············· }
上面程式碼中,程式碼1處透過Unsafe.getUnsafe()取得到Unsafe類別的實例(因為AtomicLong類別是在rt .jar包下面的,AtomicLong類別就是透過Bootstarp類別載入器進行載入的)。代碼5處,value被聲明為volatile類型,保證記憶體的可見性。透過程式碼2,4取得value變數在AtomicLong類別中的偏移。
接下來介紹AtomicLong中的主要函數:
#遞增和遞減程式碼
//调用unsafe方法,设置value=value+1后,返回原始的值 public final long getAndIncrement() { return unsafe.getAndAddLong(this, valueOffset, 1L); } //调用unsafe方法,设置value=value-1后,返回原始的值 public final long getAndDecrement() { return unsafe.getAndAddLong(this, valueOffset, -1L); } //调用unsafe方法,设置value=value+1后,返回递增后的值 public final long incrementAndGet() { return unsafe.getAndAddLong(this, valueOffset, 1L) + 1L; } //调用unsafe方法,设置value=value-1后,返回递减后的值 public final long decrementAndGet() { return unsafe.getAndAddLong(this, valueOffset, -1L) - 1L; }
上面的四個函數內部都是透過呼叫Unsafe的getAndAddLong方法來實現操作,這個函數是個原子性操作,這裡第一個參數是AtomicLong實例的引用的,第二個參數是value變數在AtomicLong的偏移值,第三個參數是要設定的第二個變數的值。
其中getAndIncrement()方法在JDK7中實作邏輯為:
public final long getAndIncrement() { while(true) { long current = get(); long next = current + 1; if (compareAndSet(current, next)) return current; } }
如上程式碼中,每個執行緒是先拿到變數的目前值(由於value是volatile變量,所以這是取得的最新值),然後在工作記憶體中進行增1操作,而後使用CAS修改變數的值,如果設定失敗,則循環繼續嘗試,直到設定成功。
JDK8中的邏輯為:
public final long getAndIncrement() { retrturn unsafe.getAndAddLong(this, valueOffset, 1L); }
#其中JDK8中的unsafe.getAndAddLong的程式碼為:
#public final long getAndAddLong(Object var1, long var2, long var4) { long var6; do { var6 = this.getLongVolatile(var1, var2); } while(!this.compareAndSwapLong(var1, var2, var6, var6 + var4)); return var6; }
從中可以看到,JDK7中的AtomicLong中循環邏輯已經被JDK8中的原子操作類Unsafe內建了。
boolean compareAndSet(long expect,long update)
public final boolean compareAndSet(long expect,long update) { return unsafe.compareAndSwapLong(this, valueOffset, expect, update); }
函數在內部呼叫了unsafe.compareAndSwapLong方法。如果原子變數中的value值等於expect,則使用update值更新該值並傳回true,否則傳回false。
以上是Java原子操作類別源碼解析的詳細內容。更多資訊請關注PHP中文網其他相關文章!