プロジェクトの1つでvolatile
を使用して、異なるスレッドによってアクセスされる変数の同じコピーを維持します。私の質問は、volatile
をstatic
と併用しても問題ないかどうかです。コンパイラーはエラーを出しませんが、両方を使用する理由がわかりません。
メモリモデルの仕様を読む前に、 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 。
そして、はい、あなたは static
をvolatile
とともに使用できます。彼らは異なることをします。
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
のロックは別として) 。
volatile
はstatic
と一緒に使用できます。これは、さまざまなことに影響するためです。 volatile
を使用すると、変数はすべてに複製されますthreads使用する前にその変数を使用しますが、static
はすべての変数を1つの変数で共有しますクラスその変数を使用します。 (これは、すべてのThread
がたまたまclass
として実装されるため、Javaでのスレッド処理に慣れていない人にとっては、かなり混乱する可能性があります。)
volatile
は、変数が実行時に変更され、コンパイラーが何らかの理由でその値をキャッシュしてはならないことを意味します。
これは、スレッド間で変数を共有する場合にのみ実際に問題となります。古いデータを処理するスレッドが望ましくないため、コンパイラーはvolatile
変数参照の値をキャッシュしないでください。
Volatileは、複数のスレッドが同じ変数にアクセスする必要があるさまざまな状況で使用されます。マルチスレッド/並行プログラミングを行わない多くの人々はこれにさらされないでしょう。揮発性は、変数がキャッシュ/レジスタバージョンからではなく、メインメモリから常に読み取られることを保証します。 Volatile自体はロックではありません。変更が書き込まれた直後にすべてのスレッドで確認されるからといって、アトミックな方法で比較および交換できることを意味するわけではありません。ただし、この機能は、Javaの待機通知セマンティクスの「より重い」ユーザーを必要とせずに、スレッドセーフなデータ構造を構築するための比較およびスワップなどの他の機能と併用できます。
あなたはこのリンクでより多くの情報を得ることができます http://www.quora.com/Threading-in-Java/What-is-the-purpose-of-the-volatile-keyword-in-Java
2つのスレッド(Thread1とThread2)が値1の同じ変数 'mObject'にアクセスしているシナリオを考えます。
thread1が実行されるとき、他のスレッドが変数「mObject」を変更することは想定されていません。このシナリオでは、Thread1は変数「mObject」を値1でキャッシュします。
また、スレッド2が「mObject」の値を2に変更した場合でも、スレッド1はキャッシュを行ったため、mObject値を1として参照します。このキャッシュを回避するには、変数を次のように宣言する必要があります
プライベート揮発性int mObject;
このシナリオでは、Thread1はmObjectの更新された値を取得します
少々複雑ですが、volatileキーワードはメモリを可視化するためだけのものではありません。以前Java ver 1.5
がリリースされ、揮発性キーワードが宣言されました。フィールドは、読み取りのたびにメインメモリにアクセスし、書き込みのフラッシュを行うことにより、オブジェクトの最新の値を取得することを宣言しました。
最新のJavaバージョンでは、volatileキーワードは2つの非常に重要なことを示しています:
その他の Java volatile の例を確認してください。