在Java中阻塞队列

时间:2013-04-20 22:33:56

标签: java multithreading synchronization synchronized

我正在阅读一本名为“Beginning Algorithms”的书,其中有Java的例子。在关于队列的章节中,它解释了“阻塞队列”,并且......即使我的背景是C#而不是Java,对我来说看起来很有趣。

这是代码的一部分(我省略了非相关部分):

public void enqueue(Object value){
    synchronized(_mutex){
        while(size == _max_size){
            waitForNotification();
        }
        _queue.enqueue(value);
        _mutex.notifyAll();
    }
}

private void waitForNotification(){
    try {
        _mutex.wait();
    } catch( InterruptedException e){
        // Ignore
    }
}

public Object dequeue() throws EmptyQueueException {
    synchronized(_mutex){
        while(isEmpty()){
            waitForNotification();
        }
        Object value = _queue.dequeue();
        _mutex.notifyAll();
        return value;
    }
}

我看到两个主要问题。

首先,如果队列已满,5个线程正在等待添加项目,而其他线程出列1项,其他5个将被释放,将同时检查“size()== _max_size”不是再次为true,他们将尝试5次调用“_queue.enqueue”,溢出队列。

其次,“出队”也是如此。如果几个线程被阻塞,试图使项目出队,因为队列是空的,添加一个将导致所有队列检查队列不再是空的,并且所有这些线程将尝试出队,获取null或我猜的异常。

我是对的吗?我C#有一个“Monitor.Pulse”只发布一个被阻塞的线程,那会是解决方案吗?

干杯。

1 个答案:

答案 0 :(得分:1)

您无视synchronized声明。这只允许一个线程获取_mutex。因此,只有一个线程才能检查size的值,因为while语句在synchronized块内。

正如this thread中所述,wait()方法实际上会释放_mutex对象,并在此情况下等待notify()notifyAll()的调用。此外,notifyAll()只会将_mutex上的锁定授予等待线程的一个