简体   繁体   English

我可以在Java中使用两个充当锁的对象来实现阻塞队列吗?

[英]Can I implement blocking queue with two objects serving as locks in Java?

I am trying to understand Java's synchronized keyword, wait(), and notify() by implementing a blocking queue class. 我试图通过实现阻塞队列类来了解Java的synced关键字,wait()和notify()。 One of the blocking queue implementation is described by this article. 一个阻塞队列执行由描述物品。 However I wonder if it is possible to use two objects serving as lock to implement blocking queue? 但是我想知道是否可以使用两个对象作为锁来实现阻塞队列? Is the below code correct? 以下代码正确吗?

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);
  }
}

First of all, you cannot wait or notify on an object that you didn't synchronized on. 首先,您不能等待或通知未同步的对象。 Here you would use this.wait() and this.notifyAll. 在这里,您将使用this.wait()和this.notifyAll。

Second, you should never wait() just once without rechecking your condition. 其次,在不重新检查条件的情况下,永远不要只等待一次()。 Whatever you put in the 'if' should be in a while loop; 无论您在“ if”中输入什么内容,都应在while循环中进行; that is because you could get notified by mistake without the condition having changed, especially since you are using the monitor on the instance which anyone outside can synchronize and notify on. 那是因为您可能会在不改变条件的情况下错误地收到通知,尤其是因为您正在实例上使用监视器,外部的任何人都可以在其上进行同步和通知。 You should rather use a synchronized(privatelockobject) {}. 您应该使用Synchronized(privatelockobject){}。

This leads to your question, can you synchronize 2 + objects... Yes, by nesting synchronized blocks, but that will lead to hanging code, since the wait() call only free the one monitor you waited on, not the outer monitor. 这会引发您的问题,您是否可以同步2个以上的对象...是的,通过嵌套同步块,但这将导致代码挂起,因为wait()调用仅释放您等待的一个监视器,而不释放外部监视器。 This is therefore pointless. 因此,这是没有意义的。

If you were trying to avoid notifying both readers and writers waiting on the queue, this is an honorable thought, but you cannot do it with synchronized. 如果您试图避免通知正在排队的读者和作家,这是一个光荣的想法,但是您不能通过同步来做到这一点。 The example cited is doing it with a single monitor, and this is also why it must use notifyAll() instead of notify(), because you want to make sure to wake the proper thread waiting. 引用的示例使用单个监视器执行此操作,这也是为什么它必须使用notifyAll()而不是notify()的原因,因为您要确保唤醒适当的线程等待。 Normally you have to use ReentrantLock with 2 distinct conditions (not empty, and not full). 通常,您必须在两个不同的条件下使用ReentrantLock(不为空,并且不完整)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM