http://www.codeproject.com/Articles/28785/Thread-synchronization-Wait-and-Pulse-demystified http://www.codeproject.com/Articles/28785/Thread-synchronization-Wait-and-Pulse-demystified
Queues:
就绪队列是等待某个线程的集合
特定的锁。 Monitor.Wait 方法引入了另一个队列:
等待队列。这是必需的,因为等待脉冲是不同的
从等待获取锁开始。就像就绪队列一样,等待队列
队列是先进先出的。
推荐图案:
这些队列可能会导致意外行为。当脉冲发生时,
等待队列的头被释放并添加到就绪队列中
队列。但是,如果就绪队列中有其他线程,它们
将在释放线程之前获取锁。这是一个
问题,因为获取锁的线程可以改变状态
脉冲线程所依赖的。解决办法就是用一段时间
lock 语句内的条件
*Q = 队列。
这样,我明白当我打电话时Pulse
,它在结束之前做了两件事。首先,它从等待Q中删除一个线程到就绪Q。其次,它让就绪Q中的一个线程(不知道该线程是谁)获取锁;它不关心谁获取锁(来自等待 Q 的线程或由于某种原因处于就绪 Q 中的线程)。
如果我是对的那么why正在放一个while
before Monitor.Wait
帮助解决问题(问题 - 即使来自等待 Q 的线程没有获取锁,脉冲也会结束)?
A. 告诉我我的目的是否正确Monitor.Pulse
.
B. 为什么我需要放一个while
before 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);
}
}
}
想象一下您正在尝试编写一个生产者/消费者队列 - 您Pulse
每次生产一个物品时,消费者都需要等待,直到有物品可供消费。你可以写这样的代码:
Foo item;
lock(someMonitor)
{
while (queue.Count == 0)
{
Monitor.Wait(someMonitor);
}
item = queue.Dequeue();
}
// Use the item
假设你didn't有 while 循环,而是写道:
Foo item;
lock(someMonitor)
{
// Broken!
if (queue.Count == 0)
{
Monitor.Wait(someMonitor);
}
item = queue.Dequeue();
}
// Use the item
现在假设您已经有一个线程正在等待,然后另一个线程就在锁定语句之前......然后生产者向监视器发出脉冲(当然,并向队列添加一项)。
此时,甚至还没有获得锁的线程将成为第一个获取锁的线程是完全可行的……此时,当“等待”线程获取锁时,队列将是又空了。只需一个if
语句,如果不循环,您最终会在队列为空时出队,这会失败。
使用 while 循环,您将再次等待,直到生成下一个项目,这才是您真正想要的。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)