陷阱錯誤使用 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 包中提供的更高階別的同步物件(佇列,障礙,訊號量等),可以解決大多數同步問題。