我在我的代码中遇到了死锁的情况。我使用以下测试代码重现了这种情况(请注意行号注释)。
我有一个
现在,如果我将
我有一个
ExecuterService
,它接受 3 个任务,其中 2 个任务对同一个未初始化的对象执行同步块,这个对象应该具有 null
值。
synchronized(null){}
在 Java 中不被允许,因此我预计会在 line-2
处出现错误。然而,这个程序执行时发生了死锁。也就是说,前两个任务被第三个任务阻塞了。(请参见输出-1)现在,如果我将
line-1
更改为 Object lock = new Object();
,那么代码将无故障地运行,没有任何死锁(输出-2)。我只是想知道当我们提供一个未初始化的互斥对象时,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
.
.
.