2

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

如果我只有一个监视器(队列对象)并让生产者和消费者wait,我将必须确保调用notifyAll而不是notify调用,否则即使队列已满,生产者也可能只会向另一个等待的生产者发出信号以继续。即使有东西,也让消费者等待。另一方面notifyAll,对于许多线程和处理器来说,调用似乎不是一个可扩展的解决方案。

BlockingQueues 使用两个显示器吗?一种是生产者等待,一种是消费者等待?然后我必须以封装的方式同步队列和相关监视器。这是要走的路吗?

4

2 回答 2

4

我不确定它是如何完成的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();
        }
    }
    ...
}
于 2011-10-29T11:58:45.653 回答
0

一般来说,notifyAll()与 相比,使用是更好的方法notify()。正如您所提到的,您可以使用两个监视器对象,一个用于读取,一个用于写入访问。
使用notify()替代可能容易出错,并且notifyAll()在大多数情况下使用的性能损失可以忽略不计,并且通常不需要不同的编码,因为每个等待的线程都必须为虚假唤醒做好准备。

于 2011-10-29T12:04:17.453 回答