我可以用两个对象作为 Java 中的锁来实现阻塞队列吗?
Can I implement blocking queue with two objects serving as locks in Java?
我试图通过实现阻塞队列 class 来理解 Java 的同步关键字 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);
}
}
首先,您不能在未同步的对象上等待或通知。在这里你会使用 this.wait() 和 this.notifyAll.
其次,你不应该在没有重新检查你的情况的情况下只等待一次。无论你在 'if' 中放入什么,都应该在一个 while 循环中;那是因为您可能会在条件未更改的情况下错误地收到通知,尤其是因为您在实例上使用监视器,任何外部人员都可以在该实例上进行同步和通知。您应该使用 synchronized(privatelockobject) {}。
这引出了您的问题,您能否同步 2 个以上的对象...是的,通过嵌套同步块,但这会导致代码挂起,因为 wait() 调用仅释放您等待的一个监视器,不是外部显示器。因此,这是毫无意义的。
如果你试图避免通知等待队列的读者和作者,这是一个光荣的想法,但你不能用 synchronized 做到这一点。引用的示例是使用单个监视器执行的,这也是为什么它必须使用 notifyAll() 而不是 notify() 的原因,因为您要确保唤醒等待的正确线程。通常你必须在 2 个不同的条件下使用 ReentrantLock(不是空的,也不是满的)。
我试图通过实现阻塞队列 class 来理解 Java 的同步关键字 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);
}
}
首先,您不能在未同步的对象上等待或通知。在这里你会使用 this.wait() 和 this.notifyAll.
其次,你不应该在没有重新检查你的情况的情况下只等待一次。无论你在 'if' 中放入什么,都应该在一个 while 循环中;那是因为您可能会在条件未更改的情况下错误地收到通知,尤其是因为您在实例上使用监视器,任何外部人员都可以在该实例上进行同步和通知。您应该使用 synchronized(privatelockobject) {}。
这引出了您的问题,您能否同步 2 个以上的对象...是的,通过嵌套同步块,但这会导致代码挂起,因为 wait() 调用仅释放您等待的一个监视器,不是外部显示器。因此,这是毫无意义的。
如果你试图避免通知等待队列的读者和作者,这是一个光荣的想法,但你不能用 synchronized 做到这一点。引用的示例是使用单个监视器执行的,这也是为什么它必须使用 notifyAll() 而不是 notify() 的原因,因为您要确保唤醒等待的正确线程。通常你必须在 2 个不同的条件下使用 ReentrantLock(不是空的,也不是满的)。