考虑以下阻塞生产者和消费者线程的实现:
static void Main(string[] args)
{
var syncRoot = new object();
var products = new List<int>();
Action producer = () => {
lock (syncRoot)
{
var counter = 0;
while (true)
{
products.Add(counter++);
Monitor.Pulse(syncRoot);
Monitor.Wait(syncRoot);
}
}};
Action consumer = () => {
lock (syncRoot)
while (true)
{
Monitor.Pulse(syncRoot);
products.ForEach(Console.WriteLine);
products.Clear();
Thread.Sleep(500);
Monitor.Wait(syncRoot);
}};
Task.Factory.StartNew(producer);
Task.Factory.StartNew(consumer);
Console.ReadLine();
}
假设当生产线程进入时Monitor.Wait
,它等待两件事:
- 从消费者线程脉冲,和
- 用于重新获得锁
在上面的代码中,我在Pulse
andWait
调用之间进行了消耗性的工作。
所以如果我这样写我的消费线程(等待前立即脉冲):
Action consumer = () =>
{
lock (syncRoot)
while (true)
{
products.ForEach(Console.WriteLine);
products.Clear();
Thread.Sleep(500);
Monitor.Pulse(syncRoot);
Monitor.Wait(syncRoot);
}
};
我没有注意到行为有任何变化。有什么指导方针吗?我们通常应该Pulse
紧接在我们之前Wait
还是在性能方面可能存在差异?