我正在閱讀一本名爲「Beginning Algorithms」的書,它有Java中的示例。在關於隊列的章節中,它解釋了「阻塞隊列」,並且......即使當我的背景是C#而不是Java時,對我來說有些東西很有趣。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次,使隊列溢出。
其次,「出列」同樣如此。如果有幾個線程因爲隊列爲空而試圖將隊列出隊時被阻塞,添加一個線程將導致他們全部檢查隊列不再爲空,並且所有隊列都將試圖出隊,獲得空值或我認爲是異常。
對嗎?我C#有一個「Monitor.Pulse」,只發佈一個阻塞的線程,這是解決方案嗎?
乾杯。
即使您的所有五個假設線程都可能在notifyAll()後喚醒,但只有一個線程將獲取_mutex並輸入synchronized塊。其餘的將回到睡眠狀態(編輯:仍在等待進入同步塊) – wobbals 2013-04-20 22:37:10
看起來像你的(幻數)5個線程正在使用相同的隊列,所以實現是說讓其他對象等待一個線程正在添加或刪除隊列中的元素。 – 2013-04-20 22:37:36
如果5個線程在「_mutex.wait()」中被阻塞,如果我調用「_mutex.notifyAll()」,它們已經在同步塊內,只有一個線程會喚醒? – vtortola 2013-04-20 22:43:36