陷阱錯誤使用 wait() notify()
方法 object.wait()
,object.notify()
和 object.notifyAll()
旨在以非常特定的方式使用。 (參見 http://stackoverflow.com/documentation/java/5409/wait-notify#t=20160811161648303307 )
失去通知問題
一個常見的初學者錯誤是無條件地稱之為 object.wait()
private final Object lock = new Object();
public void myConsumer() {
synchronized (lock) {
lock.wait(); // DON'T DO THIS!!
}
doSomething();
}
這是錯誤的原因是它依賴於其他一些執行緒來呼叫 lock.notify()
或 lock.notifyAll()
,但沒有什麼能保證其他執行緒在消費者執行緒叫做 lock.wait()
之前沒有進行該呼叫。
如果某個其他執行緒尚未等待通知,lock.notify()
和 lock.notifyAll()
根本不做任何事情。在此示例中呼叫 myConsumer()
的執行緒將永遠掛起,如果為時太晚而無法捕獲通知。
非法監控狀態錯誤
如果你在一個物件上呼叫 wait()
或 notify()
而不持有鎖,那麼 JVM 將丟擲 IllegalMonitorStateException
。
public void myConsumer() {
lock.wait(); // throws exception
consume();
}
public void myProducer() {
produce();
lock.notify(); // throws exception
}
(wait()
/ notify()
的設計要求鎖定,因為這是避免系統競爭條件所必需的。如果可以在沒有鎖定的情況下呼叫 wait()
或 notify()
,那麼就不可能實現這些原語的主要用例:等待條件發生。)
等待/通知太低階別
避免 wait()
和 notify()
問題的最好方法是不使用它們。通過使用 java.utils.concurrent
包中提供的更高階別的同步物件(佇列,障礙,訊號量等),可以解決大多數同步問題。