【发布时间】:2012-08-20 17:04:38
【问题描述】:
http://www.codeproject.com/Articles/28785/Thread-synchronization-Wait-and-Pulse-demystified
队列:
就绪队列是等待一个线程的集合 特定的锁。 Monitor.Wait 方法引入了另一个队列: 等待队列。这是必需的,因为等待脉冲是不同的 从等待获取锁。就像就绪队列一样,等待 队列是先进先出的。
推荐模式:
这些队列可能导致意外行为。当脉冲发生时, 等待队列的头部被释放并被添加到就绪队列中 队列。但是,如果就绪队列中还有其他线程,它们 将在线程被释放之前获取锁。这是一个 问题,因为获取锁的线程可以改变状态 脉冲线程所依赖的。解决方法是使用一段时间 lock 语句中的条件
*Q = 队列。
据我所知,当我打电话给Pulse 时,它会在结束前做两件事。首先,它将等待 Q 中的一个线程移到就绪 Q。其次,它让 Ready Q 中的一个线程(不知道那个线程是谁)获得锁;它不关心谁获得了锁(来自等待 Q 的线程或出于某种原因在就绪 Q 中的线程)。
如果我是对的,那么 为什么 在 Monitor.Wait 之前放置一个 while 有助于解决问题(问题 - 即使线程来自等待 Q没有获得锁)?
一个。 告诉我Monitor.Pulse 的用途是否正确。
B。 为什么我需要在Monitor.Wait之前加一个while
答案的完整代码如下:
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);
}
}
}
【问题讨论】: