Получение из std :: queue интенсивно использует ЦП в многопоточной среде - PullRequest
0 голосов
/ 07 августа 2020

Обратите внимание на следующий многопоточный псевдокод C ++. (Нет C ++ 11)

Mutex mtx;

addToQueueFromManyThreads()
{
    mtx.lock;
    pushTowriteQueue();
    mtx.unLock();
}

run()  
{
   std::string nextMessage = fetchNext();

   while ( !nextMessage.empty()  )
   {
       //  writeToFile( nextMessage );
       //  (void)SchedYield();
       nextMessage = fetchNext();   
    }
    delay( 25 ms );
}


std::string CTraceFileWriterThread::fetchNext() 
{
    std::string message;
 
    mtx.lock;
    if( !writeQueue.empty() )
    {
      message = writeQueue.front();
      writeQueue.pop();
    }
    mtx.unLock();

    return message;
}
  1. Нет большой разницы с или без 'writeToFile' или 'SchedYield'.
  2. Я работаю в потоке с низким приоритетом
  3. Весь процесс завершается из-за высокой загрузки ЦП из-за приведенного выше кода
  4. addToQueueFromManyThreads вызывается приложением, так как есть много сообщений, которые должны регистрироваться каждую секунду

На этом этапе мне интересно, использую ли я правильную структуру данных, и я перепробовал все, что мог, и у меня закончились варианты. Приветствуется любая помощь в том, что может происходить.

1 Ответ

2 голосов
/ 07 августа 2020

Лог c в run() ошибочен. Он эффективно работает без остановки, снова и снова проверяя, есть ли в очереди сообщение, которое нужно принять. Если нет, что он делает? Он проверяет еще раз, в слабой надежде, что новое сообщение пришло в последнюю миллисекунду или около того. Вот почему вы сильно загружаете процессор. Тот факт, что большую часть времени он проводит с заблокированным мьютексом, предотвращая блокировку мьютекса другими потоками выполнения, которые хотят добавить новое сообщение в очередь, тоже не помогает.

Учебное решение для правильно реализовать это, просто используя переменную условия и ожидая ее. Переменные условия существовали до C ++ 11 и доступны в POSIX. Это переведет поток выполнения в спящий режим, полностью остановив всю активность ЦП, пока переменная условия не получит сигнал от другого потока выполнения после добавления нового сообщения в очередь. Вы не можете исправить это без использования условной переменной, других практических альтернатив нет.

Как использовать условную переменную объясняется в каждом учебнике C ++, который охватывает потоки выполнения и POSIX, где я направлю вас для получения дополнительной информации , и примеры, тем более что показанный код является псевдокодом. Вам следует потратить некоторое время на изучение этого материала, чтобы понять и изучить правильный способ использования условных переменных и их семантику. Неправильное использование не поможет и, вероятно, только усугубит ситуацию.

...