我認爲有一個競賽條件ProducerConsumerQueue
從
http://www.albahari.com/threading/part2.aspx#_Signaling_with_Event_Wait_Handles。下面是代碼:ProducerConsumerQueue的競爭條件來自線程在C#
using System;
using System.Threading;
using System.Collections.Generic;
class ProducerConsumerQueue : IDisposable
{
EventWaitHandle _wh = new AutoResetEvent (false);
Thread _worker;
readonly object _locker = new object();
Queue<string> _tasks = new Queue<string>();
public ProducerConsumerQueue()
{
_worker = new Thread (Work);
_worker.Start();
}
public void EnqueueTask (string task)
{
lock (_locker) _tasks.Enqueue (task);
_wh.Set();
}
public void Dispose()
{
EnqueueTask (null); // Signal the consumer to exit.
_worker.Join(); // Wait for the consumer's thread to finish.
_wh.Close(); // Release any OS resources.
}
void Work()
{
while (true)
{
string task = null;
lock (_locker)
if (_tasks.Count > 0)
{
task = _tasks.Dequeue();
if (task == null) return;
}
if (task != null)
{
Console.WriteLine ("Performing task: " + task);
Thread.Sleep (1000); // simulate work...
}
else
_wh.WaitOne(); // No more tasks - wait for a signal
}
}
}
考慮以下執行,其中C是消費者線程,P是生產線和T1,T2,T3是執行時間:
T1: C不進入任務執行,因爲隊列爲空
lock (_locker)
if (_tasks.Count > 0)
T2: P調用EnqueueItem(action)
T3: C到達_wh.WaitOne();
和永遠等待(假定生產者停止添加新值)
書中的錯誤?廢話!在嚴重的一面,生產者是你的* EnqueueTask調用。我不明白你的評論't1',你參考消費者的代碼的和平,並說生產者。 – Sinatr
「工作」消耗隊列,而任何調用「EnqueueTask」的人都會產生項目。只有當null任務入隊時,worker循環纔會退出,並且通常應該坐在等待Set事件的最後一行。但同意分支數量和推理超過null在消費者循環中看起來相當費力。當然,在生產代碼中,我們會使用像ConcurrentQueue這樣更可信的機制。 – StuartLC
爲什麼代碼會在'_wh.WaitOne()'處「永遠等待」?調用'EnqueueItem(action)'的代碼將在某個時刻調用'_wh.Set()'。 –