最初にソース コードの一部を見てみましょう:
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; } ············省略部分代码············· }
上記のコードでは、Unsafe クラスのインスタンスは、コード 1 の Unsafe.getUnsafe() を通じて取得されます。 (AtomicLong クラスは .jar パッケージの下の rt にあるため、AtomicLong クラスは Bootstarp クラス ローダーを通じてロードされます)。コード 5 では、メモリの可視性を確保するために、値が volatile 型として宣言されています。コード 2 と 4 を使用して、AtomicLong クラスの value 変数のオフセットを取得します。
次に、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; }
上記の 4 つの関数操作は、Unsafe の getAndAddLong メソッドを呼び出すことによって内部的に実装されます。この関数はアトミック操作です。ここでの最初のパラメータは、AtomicLong インスタンスへの参照です。2 番目のパラメータは、AtomicLong の値変数のオフセット値です。3 番目のパラメータは、値です設定する 2 番目の変数の値。
JDK7 の getAndIncrement() メソッドの実装ロジックは次のとおりです。
public final long getAndIncrement() { while(true) { long current = get(); long next = current + 1; if (compareAndSet(current, next)) return current; } }
上記のコードでは、各スレッドはまず変数の現在の値を取得します (値は揮発性変数であるため、これは取得された最新の値です)、作業メモリ内で 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 メソッドを呼び出します。アトミック変数の値が Expect と等しい場合は、更新値を使用して値を更新し、true を返します。それ以外の場合は、false を返します。
以上がJava アトミック操作クラスのソース コード分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。