Java アトミック操作クラスのソース コード分析

WBOY
リリース: 2023-04-21 11:31:07
転載
1358 人が閲覧しました

最初にソース コードの一部を見てみましょう:

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 サイトの他の関連記事を参照してください。

関連ラベル:
ソース:yisu.com
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート