1

我有两个线程,一个生产者和一个消费者。

生产者可能并不总是在生产某些东西。然而,消费者需要在它可用时立即消费它。

生产者线程循环工作并将结果放入ConcurrentQueue. 消费者线程处于循环中,当系统被禁用时while (!disposing)调用。AutoResetEvent.WaitOne我也考虑AutoResetEvent.WaitOneConcurrentQueue.TryDequeue方法返回 false 的情况下调用;只有当队列中没有剩余项目时才会发生这种情况。

但是,如果我这样做,则在完成以下执行时可能会发生死锁:

  1. 入队
  2. TryDequeue 返回 true
  3. TryDequeue 返回 false
  4. 入队
  5. 维一

这是此片段中的一种可能性:

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);
}

不使用锁的正确方法是什么?

4

2 回答 2

1

我认为 BlockingCollection 在这里使用会很好。它将有效地等待,直到队列中有数据。您可以将其与我认为的 ConcurrentQueue 结合使用。请参阅http://msdn.microsoft.com/en-us/library/dd267312.aspx

于 2012-09-24T13:56:13.710 回答
0

这里的问题是线程暂停在几乎所有操作系统中都是内核级事件。我认为使用 Fibers 的 Windows 允许用户级暂停/取消暂停,但这就是我所知道的。

所以你和你的队列一起无锁地呼啸而过,但是当队列中有东西时你如何发出信号呢?

发信号意味着睡觉——这就是问题所在。你可以做无锁信号,但是等待,好吧,你必须调用操作系统等效的 WaitForEvent(),这是一个问题,因为你不想使用这些缓慢的,操作系统提供的机制。

基本上,目前还没有或很少有操作系统支持。

于 2012-09-28T13:51:20.613 回答