陷阱错误使用 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 包中提供的更高级别的同步对象(队列,障碍,信号量等),可以解决大多数同步问题。