我试图通过实现阻塞队列类来理解Java的synchronized关键字,wait()和notify()。 this文章描述了其中一个阻塞队列实现。但是我想知道是否可以使用两个对象作为锁来实现阻塞队列?以下代码是否正确?
public class BlockingQueue {
private List<Object> queue = new LinkedList<Object>();
private int limit;
private Object slots = new Object();
private Object objs = new Object();
public BlockingQueue(int limit) {
this.limit = limit;
}
private synchronized void enqueue(Object o)
throws InterruptedException {
if (queue.size() == limit)
slots.wait();
objs.notify();
queue.add(o);
}
private synchronized Object dequeue()
throws InterruptedException {
if (queue.size() == 0)
objs.wait();
slots.notify();
return queue.remove(0);
}
}
答案 0 :(得分:1)
首先,您不能等待或通知您未同步的对象。在这里你可以使用this.wait()和this.notifyAll。
其次,如果不重新检查你的状况,你就不应该等待一次。无论你在'if'中放入什么都应该在while循环中;这是因为你可以在没有条件改变的情况下错误地收到通知,特别是因为你在实例上使用监视器,外面的任何人都可以同步和通知。您应该使用synchronized(privatelockobject){}。
这导致你的问题,你可以同步2 +对象......是的,通过嵌套同步块,但这将导致挂起代码,因为wait()调用只释放你等待的一个监视器,而不是外部监视器。因此这毫无意义。
如果你试图避免通知读者和作者在队列中等待,这是一个光荣的想法,但你不能用synchronized来做。引用的示例是使用单个监视器执行此操作,这也是为什么它必须使用notifyAll()而不是notify(),因为您要确保唤醒正确的线程等待。通常,您必须使用具有2个不同条件的ReentrantLock(非空,而不是完整)。