http://www.codeproject.com/Articles/28785/Thread-synchronization-Wait-and-Pulse-demystifiedMonitor.Pulse & Warten - unerwartetes Verhalten
Queues:
die Bereitschaftswarteschlange ist die Sammlung von Threads, die für eine bestimmte Sperre warten. Die Monitor.Wait-Methoden führen eine andere Warteschlange ein: die Warteschlange. Dies ist erforderlich, da Warten auf einen Impuls Warten auf eine Sperre warten. Wie die Bereit-Warteschlange ist die wartende Warteschlange FIFO.
Empfohlene Muster:
Diese Warteschlangen zu unerwartetem Verhalten führen kann. Wenn ein Impuls auftritt, wird der Kopf der Warteschlange in freigegeben und der Bereit- -Warteschlange hinzugefügt. Wenn sich in der Bereitschaftswarteschlange jedoch weitere Threads befinden, werden sie von vor dem Thread abgerufen, der freigegeben wurde. Dies ist ein Problem, weil der Thread, der die Sperre erwirbt, den Status ändern kann, auf den sich der gepulste Thread stützt. Die Lösung ist eine während Zustand innerhalb des Schloss Anweisung verwenden
* Q = Queue.
Damit verstehe ich, dass, wenn ich Pulse
aufrufen, es 2 Dinge, bevor es endet. Erstens entfernt es einen Thread vom wartenden Q zum fertigen Q. Zweitens lässt es einen Thread (ohne zu wissen, wer dieser Thread ist) im Ready Q das Schloss zu erhalten; Es ist egal, wer die Sperre erwirbt (der Thread, der aus dem wartenden Q oder einem Thread kommt, der aus irgendeinem Grund in dem bereiten Q war).
Wenn ich richtig darüber dann warum übt eine while
vorher Monitor.Wait
hilft, das Problem zu beheben (Problem - der Impuls endet, selbst wenn der Faden, der aus dem Warte Q kam nicht das Schloss erworben hat)?
A. Sag mir, wenn ich über den Zweck von Monitor.Pulse
richtig bin.
B. Warum muss ich unten ein while
vor Monitor.Wait
Der vollständige Code der Antwort setzen:
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);
}
}
}
Vielen Dank, ich habe den vollständigen Code Ihres Beispiels geschrieben und mit Ihrer Erklärung habe ich es 90 mal getestet und ich verstehe es jetzt vollständig. Danke Agian! –