在Java中,每当我们需要调用wait/notify/notifyAll时,我们都需要访问对象监视器(通过synchronized方法或通过synchronized块)。所以我的问题是为什么java不采用同步等待/通知方法来消除从同步块或方法调用这些方法的限制。
如果这些被声明为同步,它将自动获取监视器访问权限。
对于notify和notifyAll,您的想法的问题在于,当您通知时,您通常还会在同一个同步块中执行其他操作。因此,使通知方法同步不会给你带来任何好处,你仍然需要该块。同样,wait 必须位于同步块或方法中才能有用,例如位于自旋锁内,无论如何测试都必须同步。因此,锁定的粒度对于您的建议来说是完全错误的。
这是一个例子,这是 Java 中最简单的队列实现:
public class MyQueue<T> {
private List<T> list = new ArrayList<T>();
public T take() throws InterruptedException {
synchronized(list) {
while (list.size() == 0) {
list.wait();
}
return list.remove(0);
}
}
public void put(T object) {
synchronized(list) {
list.add(object);
list.notify();
}
}
}
因此,您可以让生产者线程将内容添加到队列中,让消费者线程将内容取出。当线程要从队列中获取某些内容时,它需要在同步块内检查列表中是否有某些内容,一旦收到通知,它需要重新获取锁并确保列表中仍然有某些内容(因为某些其他消费者线程可能会介入并抓住它)。还有“虚假唤醒”现象:你不能依赖被唤醒作为发生事情的充分证据,你需要检查你正在等待的任何条件for 实际上是 true,并且需要在同步块内完成。
在这两种情况下,都需要在持有锁的情况下进行围绕等待的检查,以便当代码根据这些检查采取操作时,它知道这些结果当前是有效的。
(如果您的用例没有如上所述需要更改的状态,则同步可能是不适合该工作的工具。使用其他一些方法,例如 CountdownLatch,可能会为您提供更简单的解决方案。)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)