以下は、相互排除について学び始めたJavaプログラムです。
class MutexVar{
public static int Turn = 1;
}
class CriticalSection{
private static int modelNumber =0;
public static void setModelNumber(int number){
modelNumber = number;
}
public static int getModelNumber(){
return modelNumber;
}
}
public class MutualExclusion{
public static void main(String[] args){
Thread threadObjRef = new Thread(new Runnable(){
public void run(){
int autoVar = 1;
int newModelNumber = -1;
while(true){
/* Non - critical section - start */
System.out.println("\n" + "In run() thread");
/* Non - critical section - end */
while(MutexVar.Turn == 2){
//System.out.println("loop-run"); //infinite loop problem is here
}
/* Critical Section -start */
CriticalSection.setModelNumber(autoVar);
newModelNumber = CriticalSection.getModelNumber();
MutexVar.Turn = 2;
/* Critical Section -end */
/* Non - critical section - start */
System.out.println("run() thread: " + newModelNumber + "\n");
autoVar = autoVar + 2;
/* Non - critical section - end */
}
}
});
threadObjRef.start();
int autoVar = 0;
int newModelNumber = -1;
while(true){
/* Non - critical section - start */
System.out.println("\n" + "In main thread");
/* Non - critical section - end */
while(MutexVar.Turn == 1){
//System.out.println("loop-main"); //infinite loop problem is here
}
/* Critical Section -start */
CriticalSection.setModelNumber(autoVar);
newModelNumber = CriticalSection.getModelNumber();
MutexVar.Turn = 1;
/* Critical Section -end */
/* Non - critical section - start */
System.out.println("main- thread: " + newModelNumber + "\n");
autoVar = autoVar + 2;
/* Non - critical section - end */
}
}
}
私の質問:
1)設定する2つのスレッド間にデータ競合がありMutexVar.Turn
ますか?
2)いいえの場合、このプログラムは私には良さそうですが、私のプログラムは以下の出力で無限にループします。なぜ無限ループなのloop-run
かloop-main
?
In main thread
In run() thread
run() thread: 1
In run() thread
私の観察:
これは、スレッドのスケジューリングの問題のようです。JavaスレッドはWindowsのCreateThread()
APIを使用して内部的に作成kernel32.dll
され、OSによってWindowsの1-1スレッドモデルとしてスケジュールされているため、WindowsOSに表示されることを学びました。javaプログラムは、Windows7マルチコアOSでjavajdk1.6を使用して実行されます。
共有された可変データへのアクセスを常に同期します。JIT / CPUが何をしているのかは明確ではありませんが、非揮発性を使用すると、ほぼ確実にスレッドキャッシングの問題が発生しTurn
ます。MutrexVar
として宣言する
static class MutexVar {
public static volatile int Turn = 1;
}
キーワードの揮発性は、この値を読み取る各スレッドは最新の値を持ち、コンパイラの並べ替えを禁止します。
コンパイラの並べ替えの詳細。JITコンパイラーは、コードを取得して、の読み取りを引き上げることができますTurn
。例えばそれは変形することができます
while(MutexVar.Turn == 1){
//System.out.println("loop-main"); //infinite loop problem is here
}
に
if(MutexVar.Turn == 1) {
while(true) {
//System.out.println("loop-main"); //infinite loop problem is here
}
}
これはJavaのコンパイラコントラクトに違反することはなく、パフォーマンスを劇的に向上させることができます。フィールドをvolatileと宣言すると、このタイプまたは並べ替えが防止されます。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加