我发现java并发的奇怪行为 . 请参阅下面的代码:
public class Test {
static CountDownLatch latch = new CountDownLatch(1);
public static void main(String[] args) throws UnsupportedEncodingException, InterruptedException {
final Thread t = new MyThread();
t.start();
synchronized (t) {
latch.countDown();
System.out.println("got to sleep");
t.wait();
System.out.println("wake up");
}
}
static class MyThread extends Thread {
@Override
public void run() {
try {
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (this) {
System.out.println("inside run");
// notifyAll();
}
}
}
}
在我看来,这段代码应该挂起并永远等待,但代码完成后没有任何问题,在控制台中下一步:
got to sleep
inside run
wake up
我试图找到一些关于通知锁的信息,如果线程死了,但缺乏它 . 另外我在java规范中找不到任何信息 .
但是,如果我试图锁定其他一些对象(不在线程对象上),它就像我预期的那样工作正常 .
2 回答
它's because you'等待
Thread
实例 .Thread
在内部使用wait
/notify
/notifyAll
,所以你不应该't do that yourself as well - you' ll混淆Thread
,Thread
会让你感到困惑 . 特别是,当一个线程退出时,它会调用this.notifyAll()
.从
Thread.join
的文档:通常,尝试锁定并等待没有其他任何东西可以与之交互的对象 . 这样你可以推断出对象上存在的与并发相关的操作,因为它们很难证明你的代码是正确的 . 那个's why you'经常会看到类似的东西:
正如Jon Skeet所写,在Thread对象上进行同步是个坏主意,请使用另一个:
现在这个代码永远不会结束,直到你取消注释sync.notifyAll();