[英]Monitor.Pulse & Wait - Unexpected Behaviour
http://www.codeproject.com/Articles/28785/Thread-synchronization-Wait-and-Pulse-demystified
队列:
就绪队列是等待特定锁的线程集合。 Monitor.Wait方法引入了另一个队列:等待队列。 这是必需的,因为等待Pulse与等待获取锁定不同。 与就绪队列一样,等待队列是FIFO。
推荐图案:
这些队列可能会导致意外行为。 当发生脉冲时,等待队列的头部被释放并被添加到就绪队列中。 但是,如果就绪队列中还有其他线程,则它们将在释放的线程之前获取锁定。 这是一个问题,因为获取锁的线程可以改变脉冲线所依赖的状态。 解决方案是在lock语句中使用while条件
* Q =队列。
通过这个,我明白当我打电话给Pulse
,它会在它结束之前做两件事。 首先,它将等待Q中的一个线程移除到就绪Q.其次,它允许Ready Q中的一个线程(不知道谁是该线程)获得锁定; 它并不关心谁获取锁(来自等待Q的线程或由于某种原因在准备Q中的线程)。
如果我是正确的关于为什么是放一个while
前Monitor.Wait
帮助解决这个问题(问题-脉冲结束即使从等待Q来到线程没有获取锁)?
A。 告诉我,如果我对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);
}
}
}
想象一下,您正在尝试编写生产者/消费者队列 - 每次生成项目时都会使用Pulse
,而消费者需要等到有消耗的项目。 你会写这样的代码:
Foo item;
lock(someMonitor)
{
while (queue.Count == 0)
{
Monitor.Wait(someMonitor);
}
item = queue.Dequeue();
}
// Use the item
假设你没有 while循环,而是写道:
Foo item;
lock(someMonitor)
{
// Broken!
if (queue.Count == 0)
{
Monitor.Wait(someMonitor);
}
item = queue.Dequeue();
}
// Use the item
现在假设你有一个线程已经在等待,然后是另一个线程就在lock语句之前...然后一个生产者用脉冲监视器(当然,并将一个项目添加到队列中)。
那时,完全可行的是,甚至没有锁定的线程将是第一个获取锁定的线程......此时“等待”线程获取锁定时,队列将是又空了。 只有一个if
语句,没有循环,当队列为空时,你最终会出列队列,这会失败。
使用while循环,您将再次等待,直到生成下一个项目,这是您真正想要的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.