私のコードにデッドロックのシナリオがありました。次のテストコードでシナリオを再現しました(行番号のコメントも参照してください)。Java:ロックがnullの場合、なぜこれがデッドロックですか?
私は3つのタスクを取る1 ExecuterService
、2つのタスクは、それがnull
値を持つ必要が初期化されていない同じオブジェクトの上に同期ブロックを持っています。
synchronized(null){}
はjavaで許可されていないので、私はline-2
にエラーがあります。しかし、これはデッドロックで実行されました。すなわち、最初の2つのタスクは第3のタスクによって待機されていた。
今変更した場合line-1
からObject lock = new Object();
にコードは完璧にデッドロック(出力2)なしで動作します。初期化されていないmutexオブジェクトを提供するとき、JVMで正確に何が起こっているのか疑問に思っています。 JVMがすべてのタスクで共有される静的なコピーを作成しているように見えます。したがって、デッドロック
public class Test {
Object lock; //line -1
Integer a = 10;
public static void main(String[] arg) {
new Test().doIt();
}
public void doIt() {
ExecutorService service = Executors.newFixedThreadPool(3);
service.submit(new Runnable() {
public void run() {
synchronized (Test.this.lock) { //line -2
try {
Thread.sleep(1000 * 5);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Test.this.a = (int) Thread.currentThread().getId();
System.out.println(a + " " + Thread.currentThread().getId());
}
}
});
service.submit(new Runnable() {
public void run() {
synchronized (Test.this.lock) {
try {
Thread.sleep(1000 * 5);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Test.this.a = (int) Thread.currentThread().getId();
System.out.println(a + " " + Thread.currentThread().getId());
}
}
}
);
service.submit(new Runnable() {
public void run() {
Test.this.a = (int) Thread.currentThread().getId();
while (true) {
try {
Thread.sleep(1 * 1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(a + " Main");
}
}
});
}
}
出力-1
11 Main
11 Main
11 Main
11 Main
11 Main
11 Main
11 Main
11 Main
11 Main
11 Main
11 Main
.
.
.
出力-2
11 Main
11 Main
11 Main
11 Main
9 9
9 Main
9 Main
9 Main
9 Main
9 Main
10 10
10 Main
10 Main
.
.
.
ああ、例外は捕まえられずに印刷されています。とった。そんなに愚かな私... –
@MangatRaiModi:まあ、それはあまりにも静かなことは残念です - それは問題のためのレシピ、IMOです。エラーリスナーなどを登録する簡単な方法があればうれしいでしょう... submitによって返された 'Future'をチェックして、それが完了したことを確認できますが、エラーはありません。あなたは' get() 'もちろんです。 –
ありがとう、チェックされていない例外は常に痛みです。 –