web-dev-qa-db-ja.com

Java volatile reference vs. AtomicReference

volatileからのget()およびset()メソッドを使用する場合に、AtomicReferenceオブジェクト参照とAtomicReferenceに違いはありますか?

129
auramo

簡単な答え:いいえ。

Java.util.concurrent.atomic package doc から:

アトミックのアクセスと更新のメモリ効果は、通常、揮発性の規則に従います。

  • getには、volatile変数を読み取るメモリ効果があります。
  • setには、volatile変数の書き込み(割り当て)のメモリ効果があります。

ところで、パッケージのドキュメントは非常に優れており、すべてが説明されています...


lazySet(Java 6)で導入)は、volatile変数では達成できないセマンティクスを持つ新しい操作であり、 この投稿 を参照詳しくは。

107
pgras

いいえ、ありません。

AtomicReferenceが提供する追加の機能は、compareAndSet()メソッドとフレンドです。これらのメソッドが必要ない場合、揮発性参照はAtomicReference.set()および.get()と同じセマンティクスを提供します。

40
Avi

いくつかの違いとトレードオフがあります。

  1. AtomicReference get/setを使用すると、揮発性フィールド(javadocの状態)と同じJMMセマンティクスが使用されますが、AtomicReferenceは参照のラッパーです。 フィールドへのアクセスには、さらにポインターチェイスが含まれます

  2. メモリフットプリントが乗算されます(ほとんどのVMに当てはまる圧縮されたOOP環境を想定):

    • 揮発性参照= 4b
    • AtomicReference = 4b + 16b(12bオブジェクトヘッダー+ 4b refフィールド)
  3. AtomicReferenceは、揮発性の参照よりも豊富なAPIを提供します。 AtomicFieldUpdaterを使用するか、Java 9 a VarHandleを使用して、揮発性リファレンスのAPIを取り戻すことができます。Sun.misc.Unsafeはさみで走るのが好きなら。 AtomicReference自体は、Unsafeを使用して実装されます。

したがって、どちらを選択するのが良いのはいつですか:

  • 取得/設定のみが必要ですか?揮発性フィールド、最も単純なソリューション、および最小限のオーバーヘッドを維持します。
  • 追加の機能が必要ですか?これがコードのパフォーマンス(速度/メモリオーバーヘッド)に敏感な部分である場合、AtomicReference/AtomicFieldUpdater/Unsafeのいずれかを選択します。パフォーマンスが向上します。これがデリケートなエリアでない場合は、AtomicReferenceを選択してください。ライブラリ作成者は通常、ターゲットJDK、予想されるAPIの制限、メモリの制約などに応じて、これらのメソッドを組み合わせて使用​​します。
8
Nitsan Wakart

JDKソースコード は、このような混乱に答える最良の方法の1つです。 AtomicReferenceのコードを見ると、オブジェクトストレージにvolatie変数が使用されています。

private volatile V value;

したがって、明らかにAtomicReferenceでget()およびset()を使用する場合は、volatile変数を使用するようなものです。しかし、他の読者がコメントしたように、AtomicReferenceは追加のCASセマンティクスを提供します。そのため、まずCASセマンティクスが必要かどうかを判断し、必要な場合にのみAtomicReferenceを使用します。

6
endless

AtomicReferenceは、プレーンなvolatile変数では提供されない追加機能を提供します。 APIを読んだことで、これを知ることができますが、一部の操作に役立つロックも提供します。

ただし、この追加機能が必要でない限り、プレーンなvolatileフィールドを使用することをお勧めします。

2
Peter Lawrey