31

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

4

5 に答える 5

20

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

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

staticそして、はい、で使用できますvolatile。彼らはさまざまなことをします。

于 2011-02-05T04:21:23.993 に答える
12

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

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

于 2011-02-05T04:34:10.800 に答える
12

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

スレッド 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 であることを認識した後でも、1 と見なすことができますn。これにはさまざまな非常に正当な理由があり、完全に理解することはできません。多くは速度に関するもので、一部はセキュリティに関するものです。

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

それらは異なるものに影響するため、 volatile一緒に使用できます。変数を使用するすべてのスレッドが変数を使用する前に、変更をその変数を使用するすべてのスレッドに「複製」し、その変数を使用するすべてのクラスで単一の変数を共有します。(これは、Java でのスレッド化に慣れていない人にとってはかなり混乱する可能性があります。staticvolatilestaticThreadclass

于 2011-02-05T04:38:54.437 に答える