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

时间:2016-02-03 02:05:03

标签: java multithreading mutex synchronized blockingqueue

我试图通过实现阻塞队列类来理解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);
  }
}

1 个答案:

答案 0 :(得分:1)

首先,您不能等待或通知您未同步的对象。在这里你可以使用this.wait()和this.notifyAll。

其次,如果不重新检查你的状况,你就不应该等待一次。无论你在'if'中放入什么都应该在while循环中;这是因为你可以在没有条件改变的情况下错误地收到通知,特别是因为你在实例上使用监视器,外面的任何人都可以同步和通知。您应该使用synchronized(privatelockobject){}。

这导致你的问题,你可以同步2 +对象......是的,通过嵌套同步块,但这将导致挂起代码,因为wait()调用只释放你等待的一个监视器,而不是外部监视器。因此这毫无意义。

如果你试图避免通知读者和作者在队列中等待,这是一个光荣的想法,但你不能用synchronized来做。引用的示例是使用单个监视器执行此操作,这也是为什么它必须使用notifyAll()而不是notify(),因为您要确保唤醒正确的线程等待。通常,您必须使用具有2个不同条件的ReentrantLock(非空,而不是完整)。