Java的:为什么这是一个死锁时锁定为空?
问题描述:
我有我的代码死锁情况。我使用以下测试代码复制了场景(也请看行号注释)。Java的:为什么这是一个死锁时锁定为空?
我有一个ExecuterService
这需要3个任务,任务2具有在其上没有初始化它应具有null
值相同对象的同步块。
synchronized(null){}
,所以我在line-2
预期的错误Java不允许。但是,这会执行死锁。即前两个任务等待第三个任务。 (见输出-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
.
.
.
答
你没有一个僵局 - 但只是如你预期的错误。第一和第二个任务将抛出NullPointerException
,只留下第三个任务运行。
如果在try
/catch
语句中围绕run()
正文,则可以看到此内容。
答
执行程序线程抛出异常,除非您捕获或查询它,否则不可见。例如,你可以写:
Future<?> f = service.submit(new Runnable() { ... }
,并在主要的结尾:
try {
f.get();
} catch (ExecutionException | InterruptedException e) {
e.printStackTrace();
}
会告诉你的NPE。
嗯知道了,该异常没有抓住并打印。得到它了。对我来说太愚蠢了...... –
@MangatRaiModi:好吧,不幸的是它很沉默 - 这是一个问题的解决办法,国际海事组织。如果有一种简单的注册错误侦听器或其他方法会很好......你可以通过提交来检查返回的'Future',看看它是否完成,但不是错误......你可以通过调用'得到()'当然。 –
非常感谢,unchecked异常总是疼。 –