【发布时间】:2015-05-06 15:17:39
【问题描述】:
基本上 load() 用于生产者(只有一个调度程序线程加载 _tickQueue),而 Unload 用于消费者(只有一个专用线程执行该函数)。 _tickQueue 是一个受锁保护的常规队列(我使用它自己作为 lock() 的参数)。令人惊讶的是,它导致了僵局。
public void Load(Tick tick)
{
lock (_tickQueue)
{
while (_tickQueue.Count >= CapSize)
{
Monitor.Wait(_tickQueue);
}
_tickQueue.Enqueue(tick);
if (!_receivedTickCounts.ContainsKey(tick.Underlier))
{
_receivedTickCounts.Add(tick.Underlier, 0);
}
Console.WriteLine("Received {1} ticks for {0}", tick.Underlier, ++_receivedTickCounts[tick.Underlier]);
Monitor.Pulse(_tickQueue);
}
}
private void Unload()
{
while (true)
{
try
{
Tick tick;
lock (_tickQueue)
{
while (_tickQueue.Count == 0)
{
Monitor.Wait(_tickQueue);
}
tick = _tickQueue.Dequeue();
Monitor.Pulse(_tickQueue);
}
Persist(tick);
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
}
标题中的评论在这里找到: https://msdn.microsoft.com/en-us/library/system.threading.monitor.pulse%28v=vs.110%29.aspx
我对“重要”段落的理解是:监视器类不维护状态(以 ResetEvent 的方式)意味着死锁。给出了一个具体的例子:当两个线程使用Pulse和Wait交互时,如果一个线程在另一个线程不在等待队列中时发出脉冲,那么就会发生死锁。
有人可以具体(例如,给出发生死锁的场景)指出我在程序中做错了什么吗?我没有看到任何可能导致死锁的情况。 谢谢。
===================编辑=====================
具体来说,我很想知道为什么监视器的以下编码模式突然不起作用 - 一定与 .net 中的监视器实现有关?
lock
while(wait condition is met)
{
wait()
}
// critical section: doing work
signal();// or broadcast()
unlock
【问题讨论】:
-
为什么不使用
BlockingCollection<T>? msdn.microsoft.com/en-us/library/dd267312(v=vs.110).aspx -
@SimonSvensson 嗨,西蒙。感谢您的评论。我确信有上百万种方法可以完成任务。想听听为什么我的方法不起作用。让我们将其视为一项技术练习,通过它我可以了解有关线程的更多信息。
-
请为您的问题找到一个更有意义的标题!
标签: c# .net multithreading deadlock monitor