我正在编写一个BlockingQueue,并且想知道其他实现如何解决此问题:

如果我只有一个监视器(队列对象),并让生产者和消费者wait,我将必须确保调用notifyAll而不是notify,否则即使队列已满,生产者也可能只向另一个等待中的生产者发出信号以继续。即使有可用的东西,也要让消费者等待。另一方面,对于许多线程和处理器,调用notifyAll似乎不是一个可扩展的解决方案。
BlockingQueue是否使用两个监视器?一种是生产者在等待,一种是消费者在等待?然后,我将不得不以封装的方式同步队列和相关的监视器。那是路要走吗?

最佳答案

我不确定BlockingQueue是如何完成的,但是一种可能的解决方案是使用 ReentrantLock 而不是synchronized

它具有与syncrhonized相同的语义,但提供了一些改进。特别是,它可能具有其他线程可以在其上使用wait的几种条件:

public class MyBlockingQueue<E> {
    private Lock lock = new ReentrantLock();
    private Condition notEmpty = lock.newCondition();
    private Condition notFull = lock.newCondition();

    public void put(E e) {
        lock.lock();
        try {
            while (isFull()) notFull.await();
            boolean wasEmpty = isEmpty();
            ...
            if (wasEmpty) notEmpty.signal();
        } finally {
            lock.unlock();
        }
    }

    public E take() {
        lock.lock();
        try {
            while (isEmpty()) notEmpty.await();
            boolean wasFull = isFull();
            ...
            if (wasFull) notFull.signal();
            ...
        } finally {
            lock.unlock();
        }
    }
    ...
}

10-08 18:10