队列中的竞争条件

时间:2011-10-20 14:38:47

标签: c# .net multithreading c#-4.0 race-condition

以下代码处理带有2个参数的套接字消息。它将信息放入队列并在另一个线程上处理。我的问题是,如果2条消息一个接一个地进入,然后出列并发送到方法ProcessData,ProcessData上是否存在竞争条件?

private void DataIn(long Code, string Message)
{
  if (!Started)
  {
    if (DataInQueue == null)
      DataInQueue = new Queue();
    DataInThread = new Thread(new ThreadStart(ThreadProcedure));
    DataInThreadEnding = false;
    DataInThread.IsBackground = true;
    DataInThread.Start();
    Started = true;
  }
  DataInQueue.Enqueue(new cDataIn(Code, Message));
}

private void ThreadProcedure()
{
   while (!ProgramEnding)
   {
     Queue mySyncdQ = Queue.Synchronized(DataInQueue);
     if (mySyncdQ != null && mySyncdQ.Count > 0)
     {
        cDataIn data = null;
        // Creates a synchronized wrapper around the Queue. 
        if (mySyncdQ.Count > 0)
          data = (cDataIn)mySyncdQ.Dequeue();

        ProcessData(data);
    }
  }

}

3 个答案:

答案 0 :(得分:5)

更新

队列未在代码中以线程安全的方式使用...您显示的代码不足以确定是否存在竞争条件,但使用ConcurrentQueue可以获得更好的性能。 。并且在ThreadProcedure中你可以用null调用ProcessData,据我所知,为了安全起见,ProcessData应该是可重入的,所有这些都可以工作......

使用ConcurrentQueue - 避免一些可能出现的问题......并查看专为线程安全的生产者/消费者场景设计的BlockingCollection ......两者都主要是无锁的,并且确实是快......

答案 1 :(得分:4)

是的,我认为这甚至会让你的队列处于不稳定的状态。您应该使用.Net 4附带的 Concurrent Queue BlockingCollection。它是开箱即用的线程安全并且已经过优化。

关心Gert-Jan

答案 2 :(得分:3)

您的代码不是线程安全的。请注意the documentation for Queue.Synchronized()

  

为了保证Queue的线程安全,所有操作必须仅通过此包装器完成。

您正在直接使用队列,因此代码不是线程安全的。要解决此问题,请始终使用返回的包装器,如文档所述。

或者,如果你在.Net 4下,请使用ConcurrentQueue<T>

如果您想在以前版本的.Net上使用通用队列,可以使用Queue<T>并始终在lock中访问它。