volatileObject 参照と、と-methods from をAtomicReference使用する場合との間に違いはありますか?get()set()AtomicReference
6 に答える
簡単な答えは: いいえ。
java.util.concurrent.atomicパッケージのドキュメントから。引用するには:
アトミックのアクセスと更新のメモリ効果は、通常、揮発性のルールに従います。
getvolatile変数を読み取るメモリ効果があります。set変数の書き込み (割り当て) のメモリ効果がありvolatileます。
ちなみに、そのドキュメントは非常に優れており、すべてが説明されています。
AtomicReference::lazySetvolatile変数では達成できないセマンティクスを持つ、導入された新しい (Java 6+) 操作です。詳細については、この投稿を参照してください。
いいえ、ありません。
AtomicReference によって提供される追加機能は、compareAndSet() メソッドとその仲間です。これらのメソッドが必要ない場合、揮発性参照は AtomicReference.set() および .get() と同じセマンティクスを提供します。
いくつかの違いとトレードオフがあります。
AtomicReferenceget/setを使用すると、揮発性フィールドと同じJMM セマンティクス(javadoc が述べているように) を持ちますがAtomicReference、これは参照のラッパーであるため、フィールドへのアクセスにはさらにポインタ チェイスが必要です。メモリ フットプリントは倍増します(ほとんどの VM に当てはまる、圧縮された OOP 環境を想定しています)。
- 揮発性参照 = 4b
AtomicReference= 4b + 16b (12b オブジェクト ヘッダー + 4b ref フィールド)
AtomicReferencevolatile リファレンスよりも豊富な 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フィールドを使用することをお勧めします。