プログラマが同期に使用する変数にvolatile
キーワードを追加することを忘れた場合、キャッシュの視点(MESIプロトコル)から何が起こるかを理解したいと思います。揮発性変数を使用しない同期の壊れた場合
次のコードスニペットは、一部の繰り返しの後で単純に停止します。 2スレッドの1つ(THREAD 0を仮定しよう)がcurrent
の変数をTHREAD 1によってgetNext()によって変更されていると見なしていないため、それは永遠にループしているからです。
しかし、私はなぜそれが当てはまるかわかりません。 THREAD 0はcurrent
にループしており、ある時点でキャッシュラインがTHREAD1(キャッシュラインがModifiedステートに切り替えられました)によって更新され、メモリキャッシュ上に "Read"メッセージを発行してローカルキャッシュにフェッチすることがあります。変数current
にvolatile
修飾子を追加すると、すべて正常に動作します。
THREAD 0の実行を継続できないと思われることは何ですか。
参考:Memory Barriers: a Hardware View for Software Hackers
public class Volatile {
public static final int THREAD_0 = 0;
public static final int THREAD_1 = 1;
public static int current;
public static int counter = 0;
public static void main(String[] args) {
current = 0;
/** Thread 0 **/
Thread thread0 = new Thread(() -> {
while(true) { /** THREAD_0 */
while (current != THREAD_0);
counter++;
System.out.println("Thread0:" + counter);
current = getNext(THREAD_0);
}
});
/** Thread 1 **/
Thread thread1 = new Thread(() -> {
while(true) { /** THREAD_1 */
while (current != THREAD_1);
counter++;
System.out.println("Thread1:" + counter);
current = getNext(THREAD_1);
}
});
thread0.start();
thread1.start();
}
public static int getNext(int threadId) {
return threadId == THREAD_0 ? THREAD_1 : THREAD_0;
}
}
あなたは完全に正しい、この問題は、JITコンパイラに関連しています。プログラムをインタプリタモード(-Xint)で起動すると、コンパイルモード(-Xcomp)では動作しませんが、永遠に動作します。この返答をありがとう! –