【发布时间】:2014-02-23 07:14:06
【问题描述】:
考虑以下阻塞生产者和消费者线程的实现:
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();
}
假设当 Producing 线程进入 Monitor.Wait 时,它会等待两件事:
- 用于从消费者线程发送脉冲,并且
- 用于重新获取锁
在上面的代码中,我在 Pulse 和 Wait 调用之间进行了消耗性工作。
所以如果我这样写我的消费线程(等待前立即脉冲):
Action consumer = () =>
{
lock (syncRoot)
while (true)
{
products.ForEach(Console.WriteLine);
products.Clear();
Thread.Sleep(500);
Monitor.Pulse(syncRoot);
Monitor.Wait(syncRoot);
}
};
我没有注意到行为有任何变化。有什么指导方针吗?我们通常应该在Wait 之前立即Pulse 还是在性能方面可能存在差异?
【问题讨论】:
-
如果使用 .NET 4 或更高版本,请查看 System.Collections.Concurrent 命名空间以获取新的并发集合 (msdn.microsoft.com/en-us/library/…)
-
见
BlockingCollection例如,stackoverflow.com/questions/21357933/… -
@Jason @L.B.集合很棒,但是有比共享集合更复杂的生产者/消费者场景。这就是为什么我想更多地了解
Monitor方法的工作原理。
标签: c# concurrency producer-consumer monitors