[英]Strange java behavior of wait/notify
我發現 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();
}
}
}
}
在我看來,這段代碼應該掛起並永遠等待,但是代碼已經完成,控制台中的 next out 沒有任何問題:
got to sleep inside run wake up
我試圖找到一些有關在線程死亡時通知鎖的信息,但缺少這些信息。 我也沒有在 java 規范中找到任何信息。
但是,如果我嘗試鎖定其他一些 object(不是線程對象),它會像我預期的那樣工作正常。
這是因為你正在等待一個Thread
實例。 Thread
內部使用wait
/ notify
/ notifyAll
,所以你不應該自己這樣做 - 你會混淆Thread
,而Thread
會讓你感到困惑。 特別是,當一個線程退出時,它會調用this.notifyAll()
。
從Thread.join
的文檔:
此實現使用
this.wait
調用this.isAlive
。 當一個線程終止時,將調用this.notifyAll
方法。 建議應用程序不要在Thread
實例上使用wait
,notify
或notifyAll
。
通常,嘗試鎖定並等待沒有其他任何東西可以與之交互的對象。 這樣你可以推斷出對象上存在的與並發相關的操作,因為它們非常有限。 只要任意代碼可以在對象上同步(以及調用wait / notify等),就很難證明您的代碼是正確的。 這就是為什么你經常會看到這樣的東西:
public class Foo {
private final Object lock = new Object();
... code which uses synchronized(lock) ...
}
正如Jon Skeet所寫,在Thread對象上進行同步是個壞主意,請使用另一個:
public class Test {
static CountDownLatch latch = new CountDownLatch(1);
static final Object sync = new Object();
public static void main(String[] args) throws UnsupportedEncodingException, InterruptedException {
final Thread t = new MyThread();
t.start();
synchronized (sync) {
latch.countDown();
System.out.println("got to sleep");
sync.wait();
System.out.println("wake up");
}
}
}
static class MyThread extends Thread {
@Override
public void run() {
try {
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (sync) {
System.out.println("inside run");
//sync.notifyAll();
}
}
}
現在這個代碼永遠不會結束,直到你取消注釋sync.notifyAll();
由於在 Thread 實例上進行了鎖定,因此它的行為有所不同,如果您鎖定不同的 object(或者可能是 Object obj),那么它將正常工作,即不會打印wake up
並且主線程將等待。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.