我正在阅读一本名为“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”只发布一个被阻塞的线程,那会是解决方案吗?
干杯。
答案 0 :(得分:1)
您无视synchronized
声明。这只允许一个线程获取_mutex
。因此,只有一个线程才能检查size
的值,因为while
语句在synchronized
块内。
正如this thread中所述,wait()
方法实际上会释放_mutex
对象,并在此情况下等待notify()
或notifyAll()
的调用。此外,notifyAll()
只会将_mutex
上的锁定授予等待线程的一个。