Javaの揮発性参照とAtomicReference


135

volatileオブジェクト参照とAtomicReferenceget()- set()メソッドを使用する場合の違いはありますAtomicReferenceか?

回答:


114

短い答えは次のとおりです。いいえ。

java.util.concurrent.atomicパッケージのドキュメントから。引用するには:

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

  • getvolatile変数を読み取るメモリ効果があります。
  • setvolatile変数の書き込み(割り当て)のメモリー効果があります。

ちなみに、そのドキュメントは非常に優れており、すべてが説明されています。


AtomicReference::lazySetvolatile変数を介して達成できないセマンティクスを持つ、導入された新しい(Java 6+)操作です。詳細については、この投稿を参照してください。


11
そしてより長い答えは?
ジュリアン・グレニエ

同意した。少なくともリンクが必要です。
ジュリアンチャスタン2009年


42

いいえ、ありません。

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


14

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

  1. AtomicReferenceget / setの使用は、(javadocが示すように)volatileフィールドと同じJMMセマンティクスを持ってAtomicReferenceいますが、これは参照のラッパーであるため、フィールドへのアクセスには、さらにポインターの追跡が必要です。

  2. メモリフットプリントが乗算され(ほとんどのVMについても同様である圧縮OOPS環境を想定します):

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

それで、どちらを選ぶのが良いのですか?

  • 取得/設定のみ必要ですか?揮発性フィールド、最も単純なソリューション、およびオーバーヘッドの最小化にこだわります。
  • 追加の機能が必要ですか?これは、性能(速度/メモリのオーバーヘッド)であれば、あなたのコードの敏感な部分には、間の選択をするAtomicReference/ AtomicFieldUpdater/ Unsafeあなたはパフォーマンスの向上のための読みやすさとリスクに賃金する傾向があります。これがデリケートな領域でない場合は、そのままにしてくださいAtomicReference。ライブラリの作成者は通常、対象のJDK、予想されるAPIの制限、メモリの制約などに応じて、これらの方法を組み合わせて使用​​します。

7

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

private volatile V value;

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


13
「JDKソースコードはこのような混乱に答える最良の方法の1つです」 =>必ずしも同意しません-javadoc(クラスの規約)が最良の方法です。コードで見つけたものは、特定の実装に関する質問に答えますが、コードは変更される可能性があります。
アッシリア

4
たとえば、ハッシュマップ内のこの変数はJDK 6では揮発性でしたが、Java 7ではもはや揮発性ではありませんでした。変数が揮発性であったという事実に基づいてコードを作成しましたか?JDKをアップグレードすると壊れました...確かに例は違うが要点はわかる。
アッシリア

そのCASはいくつかの標準的な略語ですか?
abbas

1
比較して交換=)
エンドレスな

4

AtomicReferenceプレーンな揮発性変数が提供しない追加機能を提供します。API Javadocを読んでいると、これがわかるでしょうが、一部の操作に役立つロックも提供されます。

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


したがって、違いはパフォーマンスにあります。違いがなければ、どちらか一方を使用することをお勧めしません。
BT

パフォーマンスはほとんど同じです。AtomicRefrenceは、複雑さとメモリ使用量を追加します。
Peter Lawrey、

@BT volatileフィールドは通常のフィールドと同じように使用できますが、の値にアクセスするには、AtomicReference通過するメソッドgetsetメソッドが必要です。
David Harkness 2014

0

getとsetのみを使用する場合でも、AtomicReferenceが適切な選択になる場合があります。

揮発性の例:

private volatile Status status;
...
public setNewStatus(Status newStatus){
  status = newStatus;
}

public void doSomethingConditionally() {
  if(status.isOk()){
    System.out.println("Status is ok: " + status); // here status might not be OK anymore because in the meantime some called setNewStatus(). setNewStatus should be synchronized
  }
}

AtomicReferenceを使用した実装では、コピーオンライト同期を無料で提供します。

private AtomicReference<Status> statusWrapper;
...

public void doSomethingConditionally() {
  Status status = statusWrapper.get();
  if(status.isOk()){
    System.out.println("Status is ok: " + status); // here even if in the meantime some called setNewStatus() we're still referring to the old one
  }
}

置き換えた場合でも、適切なコピーを持つことができると言うかもしれません:

Status status = statusWrapper.get();

と:

Status statusCopy = status;

ただし、2つ目は、将来、「コードクリーニング」中に誤って誰かによって削除される可能性が高くなります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.