volatile
Object 参照と、と-methods from をAtomicReference
使用する場合との間に違いはありますか?get()
set()
AtomicReference
6 に答える
簡単な答えは: いいえ。
java.util.concurrent.atomic
パッケージのドキュメントから。引用するには:
アトミックのアクセスと更新のメモリ効果は、通常、揮発性のルールに従います。
get
volatile
変数を読み取るメモリ効果があります。set
変数の書き込み (割り当て) のメモリ効果がありvolatile
ます。
ちなみに、そのドキュメントは非常に優れており、すべてが説明されています。
AtomicReference::lazySet
volatile
変数では達成できないセマンティクスを持つ、導入された新しい (Java 6+) 操作です。詳細については、この投稿を参照してください。
いいえ、ありません。
AtomicReference によって提供される追加機能は、compareAndSet() メソッドとその仲間です。これらのメソッドが必要ない場合、揮発性参照は AtomicReference.set() および .get() と同じセマンティクスを提供します。
いくつかの違いとトレードオフがあります。
AtomicReference
get/setを使用すると、揮発性フィールドと同じJMM セマンティクス(javadoc が述べているように) を持ちますがAtomicReference
、これは参照のラッパーであるため、フィールドへのアクセスにはさらにポインタ チェイスが必要です。メモリ フットプリントは倍増します(ほとんどの VM に当てはまる、圧縮された OOP 環境を想定しています)。
- 揮発性参照 = 4b
AtomicReference
= 4b + 16b (12b オブジェクト ヘッダー + 4b ref フィールド)
AtomicReference
volatile リファレンスよりも豊富な API を提供します。AtomicFieldUpdater
を使用するか、Java 9 a を使用して、揮発性参照の API を取り戻すことができますVarHandle
。sun.misc.Unsafe
ハサミで走るのが好きな方は、まっすぐ手を伸ばすこともできます。AtomicReference
それ自体は を使用して実装されUnsafe
ます。
では、どのような場合にどちらかを選択するのが良いでしょう:
- 取得/設定のみが必要ですか? 揮発性フィールド、最も単純なソリューション、および最小のオーバーヘッドに固執します。
- 追加機能が必要ですか? これがコードのパフォーマンス (速度/メモリ オーバーヘッド) に敏感な部分である場合は、
AtomicReference
/AtomicFieldUpdater
/Unsafe
読みやすさとパフォーマンス向上のリスクのいずれかを選択してください。これがデリケートな領域でない場合は、 を選択してAtomicReference
ください。ライブラリの作成者は通常、対象の JDK、予想される API の制限、メモリの制約などに応じて、これらの方法を組み合わせて使用します。
JDK ソース コードは、このような混乱に答える最良の方法の 1 つです。AtomicReference のコードを見ると、オブジェクト ストレージに volatie 変数が使用されています。
private volatile V value;
したがって、明らかに AtomicReference で get() と set() を使用する場合は、volatile 変数を使用するようなものです。しかし、他の読者がコメントしたように、AtomicReference は追加の CAS セマンティクスを提供します。したがって、最初に CAS セマンティクスが必要かどうかを決定し、必要な場合のみ AtomicReference を使用します。
AtomicReference
プレーンな volatile 変数が提供しない追加機能を提供します。API Javadoc を読んでいるとわかるでしょうが、一部の操作に役立つロックも提供します。
ただし、この追加機能が必要でない限り、プレーンvolatile
フィールドを使用することをお勧めします。