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