http://www.codeproject.com/Articles/28785/Thread-synchronization-Wait-and-Pulse-demystified
キュー:
レディキューは、特定のロックを待機しているスレッドのコレクションです。Monitor.Waitメソッドは、別のキュー、つまり待機キューを導入します。パルスを待つことは、ロックを取得することを待つこととは異なるため、これが必要です。レディキューと同様に、待機キューはFIFOです。
推奨パターン:
これらのキューは、予期しない動作を引き起こす可能性があります。パルスが発生すると、待機キューの先頭が解放され、準備完了キューに追加されます。ただし、レディキューに他のスレッドがある場合、それらは解放されたスレッドの前にロックを取得します。ロックを取得するスレッドは、パルススレッドが依存する状態を変更する可能性があるため、これは問題です。解決策は、lockステートメント内でwhile条件を使用することです。
*Q=キュー。
それによって、私が電話をするときPulse
、それが終わる前にそれが2つのことをすることを私は理解します。まず、待機中のQから準備完了のQに1つのスレッドを削除します。次に、準備完了のQの1つのスレッド(そのスレッドが誰であるかを知らなくても)にロックを取得させます。誰がロックを取得するかは関係ありません(待機中のQから来たスレッド、または何らかの理由で準備完了のQにあったスレッド)。
私がそれについて正しければ、なぜwhile
問題を解決するのを助ける前に置くのですかMonitor.Wait
(問題-待機中のQから来たスレッドがロックを取得しなかったとしてもパルスは終了します)?
A。 _ の目的について正しいかどうか教えてくださいMonitor.Pulse
。
B。 _ なぜwhile
前に置く必要があるのですかMonitor.Wait
以下の答えの完全なコード:
class Program
{
static Queue<int> queue = new Queue<int>();
static object someMonitor = new object();
static void Main(string[] args)
{
Thread Thread1 = new Thread(WorkAlltheTime);
Thread1.Name = "Thread1";
Thread Thread2 = new Thread(WorkAlltheTime);
Thread2.Name = "Thread2";
Thread Thread3 = new Thread(WorkOnce);
Thread3.Name = "Thread3";
Thread1.Start();
Thread2.Start();
Thread.Sleep(1000);
Thread3.Start();
Console.ReadLine();
}
static void WorkAlltheTime()
{
Console.WriteLine("Came in to Ready Q: " + Thread.CurrentThread.Name);
lock (someMonitor)
{
Console.WriteLine("Came out from Ready Q: " + Thread.CurrentThread.Name);
// Broken!
while (queue.Count == 0)
{
Console.WriteLine("Came in to Waiting Q: " + Thread.CurrentThread.Name);
Monitor.Wait(someMonitor);
Console.WriteLine("Came out from Waiting Q: " + Thread.CurrentThread.Name);
}
queue.Dequeue();
Console.WriteLine("Thread: "+Thread.CurrentThread.Name+" Pulled Out");
}
}
static void WorkOnce()
{
lock (someMonitor)
{
queue.Enqueue(1);
Monitor.Pulse(someMonitor);
}
}
}