Я пытаюсь узнать переменные условия и как использовать его в ситуации производителя-потребителя. У меня есть очередь, где один поток подталкивает числа в очередь, а другой поток выдает числа из очереди. Я хочу использовать переменную условия, чтобы сигнализировать потребляющий поток, когда есть некоторые данные, помещенные производящей нитью. Проблема в том, что есть времена (или чаще всего), которые только подталкивают до двух элементов в очередь, затем зависает. Я указал в функции production(), где он останавливается при работе в режиме отладки. Может ли кто-нибудь помочь мне указать, почему это происходит?Использование переменной условия в ситуации производителя-потребителя
я следующие глобальные переменные:
boost::mutex mutexQ; // mutex protecting the queue
boost::mutex mutexCond; // mutex for the condition variable
boost::condition_variable condQ;
Ниже мой поток-потребитель:
void consume()
{
while(!bStop) // globally declared, stops when ESC key is pressed
{
boost::unique_lock lock(mutexCond);
while(!bDataReady)
{
condQ.wait(lock);
}
// Process data
if(!messageQ.empty())
{
boost::mutex::scoped_lock lock(mutexQ);
string s = messageQ.front();
messageQ.pop();
}
}
}
Ниже мой продюсер Тема:
void produce()
{
int i = 0;
while((!bStop) && (i < MESSAGE)) // MESSAGE currently set to 10
{
stringstream out;
out << i;
string s = out.str();
boost::mutex::scoped_lock lock(mutexQ);
messageQ.push(s);
i++;
{
boost::lock_guard lock(mutexCond); // HANGS here
bDataReady = true;
}
condQ.notify_one();
}
}
FWIW, эта ошибка является прекрасным примером «блокировки инверсии». В одном потоке вы сначала блокируете mutexQ, а затем, не отпуская его, вы блокируете mutexCond. В другом потоке вы сначала блокируете mutexCond, а затем mutexQ. Это почти всегда неправильно. Один поток получает один замок, а другой - другой. Тогда они оба будут ждать, чтобы получить замок, которого у них нет. Которые они не могут получить, когда-либо. Простые решения - либо использовать меньшее количество блокировок (что в любом случае является правильным, даже если это не для инверсии), либо определить «иерархию» блокировок, поэтому вы всегда можете принимать их в последовательном порядке. –