Состояние гонки в очереди - PullRequest
       14

Состояние гонки в очереди

1 голос
/ 20 октября 2011

Приведенный ниже код обрабатывает сообщение сокета, которое приходит с 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 ]

5 голосов
/ 20 октября 2011

ОБНОВЛЕНИЕ

Очередь не используется потокобезопасным способом в вашем коде ... показанного вами кода недостаточно, чтобы убедиться в наличии состояния гонки, но с ConcurrentQueue, который вы получаетелучшая производительность ... и в ThreadProcedure у вас может быть вызов ProcessData со значением NULL, и, насколько я могу судить, чтобы быть в безопасности, ProcessData должен быть повторно входящим, чтобы все это работало ...

ИспользуйтеConcurrentQueue - это позволяет избежать некоторых возможных проблем ... и посмотрите BlockingCollection, который предназначен для поточно-ориентированных сценариев "производитель / потребитель" ... оба работают в основном без блокировкии очень быстро ...

4 голосов
/ 20 октября 2011

Да, я думаю, что это может даже привести вашу очередь в непостоянное состояние. Вы должны использовать Одновременную очередь BlockingCollection , которая поставляется с .Net 4. Она поточна из коробки и оптимизирована.

С уважением, Герт-Ян

3 голосов
/ 20 октября 2011

Ваш код не является потокобезопасным.Обратите внимание на это в документации Queue.Synchronized():

Чтобы гарантировать безопасность потока Queue, все операции должны выполняться только через эту оболочку.

Вы используете очередь напрямую, поэтому код не является поточно-ориентированным.Чтобы это исправить, всегда используйте только возвращенную оболочку, как сказано в документации.

Или, если вы находитесь под .Net 4, используйте ConcurrentQueue<T>.

Если вы хотите использовать genericочереди в предыдущей версии .Net, вы могли бы использовать Queue<T> и всегда иметь к нему доступ в lock.

...