web-dev-qa-db-ja.com

Javaで「揮発性」とはどういう意味ですか?

プロジェクトの1つでvolatileを使用して、異なるスレッドによってアクセスされる変数の同じコピーを維持します。私の質問は、volatilestaticと併用しても問題ないかどうかです。コンパイラーはエラーを出しませんが、両方を使用する理由がわかりません。

27
jnivasreddy

メモリモデルの仕様を読む前に、 http://jeremymanson.blogspot.com/2008/11/what-volatile-means-in-Java.html を読むことをお勧めします。これは、JMM作成者の1人が作成したものであり、質問に答える必要があります。 happens-before 句の観点からメモリの読み取りと書き込みを考えることも役立ちます。 Java 5以降のJMMは、発生前のセマンティクスをvolatileに追加します。

具体的には、1つのスレッドから揮発性変数を読み取ると、他のスレッドからのその揮発性変数への書き込みまでのすべての書き込みが、その1つのスレッドから見えるようになります。時間があれば、このトピックについてさらに説明するGoogleの技術講演があります https://code.google.com/edu/languages/#_Java_memmodel

そして、はい、あなたは staticvolatileとともに使用できます。彼らは異なることをします。

18
ide

Javaでは、volatileはCと同様の一般的な意味を持っています。Javaメモリモデル(IDEの回答の優れたリンクを参照))により、スレッドは同時に異なる値を「見る」ことができます。不揮発性としてマークされた変数の場合。例:

スレッドa:

n = 1;
// wait...
n = 2;

スレッドBおよびC:

while (true) {
    System.out.println(name + ": " + n);
}

この出力は発生する可能性があります(BとCを厳密に交互に切り替えることが保証されているわけではありません。ここでは、BとCの「切り替え」を表示しようとしているだけです)。

C: 1
B: 1
C: 2
B: 1
C: 2
B: 2

これは、printlnが取得したロックとは完全に別のものです。スレッドBは許可であり、Cが2であることがわかった後でもnを1と見なします。これには、私が完全に理解するふりをできないさまざまな非常に良い理由があります。多くは速度に関係し、一部はセキュリティに関係しています。

揮発性である場合、BとCの両方が送信されるとすぐにBとCの両方が「同時に」Bの新しい値を見ることが保証されます(printlnのロックは別として) 。

volatilestaticと一緒に使用できます。これは、さまざまなことに影響するためです。 volatileを使用すると、変数はすべてに複製されますthreads使用する前にその変数を使用しますが、staticはすべての変数を1つの変数で共有しますクラスその変数を使用します。 (これは、すべてのThreadがたまたまclassとして実装されるため、Javaでのスレッド処理に慣れていない人にとっては、かなり混乱する可能性があります。)

11
Paul Fisher

volatileは、変数が実行時に変更され、コンパイラーが何らかの理由でその値をキャッシュしてはならないことを意味します。

これは、スレッド間で変数を共有する場合にのみ実際に問題となります。古いデータを処理するスレッドが望ましくないため、コンパイラーはvolatile変数参照の値をキャッシュしないでください。

8
user177800

Volatileは、複数のスレッドが同じ変数にアクセスする必要があるさまざまな状況で使用されます。マルチスレッド/並行プログラミングを行わない多くの人々はこれにさらされないでしょう。揮発性は、変数がキャッシュ/レジスタバージョンからではなく、メインメモリから常に読み取られることを保証します。 Volatile自体はロックではありません。変更が書き込まれた直後にすべてのスレッドで確認されるからといって、アトミックな方法で比較および交換できることを意味するわけではありません。ただし、この機能は、Javaの待機通知セマンティクスの「より重い」ユーザーを必要とせずに、スレッドセーフなデータ構造を構築するための比較およびスワップなどの他の機能と併用できます。

あなたはこのリンクでより多くの情報を得ることができます http://www.quora.com/Threading-in-Java/What-is-the-purpose-of-the-volatile-keyword-in-Java

2
Humoyun Ahmad

2つのスレッド(Thread1とThread2)が値1の同じ変数 'mObject'にアクセスしているシナリオを考えます。

thread1が実行されるとき、他のスレッドが変数「mObject」を変更することは想定されていません。このシナリオでは、Thread1は変数「mObject」を値1でキャッシュします。

また、スレッド2が「mObject」の値を2に変更した場合でも、スレッド1はキャッシュを行ったため、mObject値を1として参照します。このキャッシュを回避するには、変数を次のように宣言する必要があります

プライベート揮発性int mObject;

このシナリオでは、Thread1はmObjectの更新された値を取得します

2
Jeffy

少々複雑ですが、volatileキーワードはメモリを可視化するためだけのものではありません。以前Java ver 1.5がリリースされ、揮発性キーワードが宣言されました。フィールドは、読み取りのたびにメインメモリにアクセスし、書き込みのフラッシュを行うことにより、オブジェクトの最新の値を取得することを宣言しました。

最新のJavaバージョンでは、volatileキーワードは2つの非常に重要なことを示しています:

  1. どのように心配する必要はありませんが、揮発性フィールドを読み取るときは常に最新の値が得られることを知っておいてください。
  2. コンパイラは、プログラムの順序を維持するために、揮発性の読み取り/書き込みを並べ替えることはできません。

その他の Java volatile の例を確認してください。

0
Johnny