我有两个线程,一个生产者和一个消费者。
制片人可能并不总是在生产一些东西。然而,消费者需要在它可用时立即消费它。
生产者线程在循环中工作并将结果放入ConcurrentQueue
中。使用者线程处于while (!disposing)
循环中,当系统禁用时调用AutoResetEvent.WaitOne
。我也考虑过在 ConcurrentQueue.TryDequeue
方法返回 false 的情况下调用AutoResetEvent.WaitOne
;仅当队列中没有剩余项目时,才会发生这种情况。
但是,如果我要这样做,则在完成以下执行时可能会发生死锁:
- 排队
- TryDequeue 返回 true
- 尝试取消排队返回假
- 排队
- 等一
这是此代码片段中的可能性:
while (this.isDisposing == 0)
{
if (this.isEnabled == 0)
{
this.signal.WaitOne();
}
object item;
if (!this.queue.TryDequeue(out item))
{
this.signal.WaitOne();
continue;
}
this.HandleItem(item);
}
不使用锁的正确方法是什么?
我认为在这里使用BlockingCollection会很好。它将有效地等待,直到队列中有数据。我认为你可以把它与ConcurrentQueue结合起来。请参阅 http://msdn.microsoft.com/en-us/library/dd267312.aspx
这里的问题是线程暂停在几乎所有操作系统中都是内核级事件。 我认为使用Fibers的Windows允许用户级别的暂停/取消暂停,但这就是我所知道的。
所以你无锁地随着你的队列呼啸而过,但是当队列中首先有东西时,你如何发出信号?
信号意味着睡觉——这就是问题所在。 你可以做无锁信令,但是等待,好吧,你必须调用WaitForEvent()的操作系统等效物,这是一个问题,因为你不想使用这些缓慢的操作系统提供的机制。
基本上,目前还没有或非常轻微的操作系统支持。