在以无锁方式生成对象之前,如何暂停使用者?

时间:2012-09-23 20:08:43

标签: c# .net multithreading lock-free

我有两个主题,一个制作人和一个消费者。

制作人可能并不总是在制作某些东西。然而,消费者需要尽快消​​费它。

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

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

  1. 入队
  2. TryDequeue返回true
  3. TryDequeue返回false
  4. 入队
  5. WaitOne的
  6. 这个代码段中有可能:

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

    在不使用锁的情况下执行此操作的正确方法是什么?

2 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:0)

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

所以你无人随意地跟着你的队列一起,但是当你的队列中有什么东西时你怎么发出信号呢?

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

基本上,目前还没有或非常适合的操作系统支持。