0

我正在阅读一本名为“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”是否不再为真,并且他们将尝试调用“_queue.enqueue” 5 次,使队列溢出。

其次,同样的情况也发生在“出队”上。如果由于队列为空而阻止多个线程尝试使项目出队,添加一个将导致所有线程检查队列不再为空,并且所有线程都将尝试出队,得到 null 或我猜的异常。

我对吗?IC# 有一个“Monitor.Pulse”,它只释放一个被阻塞的线程,这会是解决方案吗?

干杯。

4

1 回答 1

1

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

As described in this thread, the wait() method actually releases the _mutex object and waits for a call to notify(), or notifyAll() in this case. Furthermore, notifyAll() will only grant the lock on _mutex to one of the waiting threads.

于 2013-04-20T22:44:38.593 回答