Я пытаюсь узнать об условных переменных и как использовать его в ситуации производителя-потребителя. У меня есть очередь, где один поток продвигает числа в очередь в то время как другое сование потока числа от очереди. Я хочу использовать условную переменную для передачи сигналов о потоке потребления, когда существуют некоторые данные, помещенные потоком создания. Проблема существуют времена (или большинство раз), что она только продвигает до двух объектов в очередь, затем зависает. Я указал в продукте () на функцию, где это останавливается при выполнении в режиме отладки. Кто-либо может помочь мне указать, почему это происходит?
У меня есть следующие глобальные переменные:
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();
}
}
Для защиты очереди необходимо использовать тот же мьютекс, что и в переменной условия.
Это должно быть все, что вам нужно:
void consume()
{
while( !bStop )
{
boost::scoped_lock lock( mutexQ);
// Process data
while( messageQ.empty() ) // while - to guard agains spurious wakeups
{
condQ.wait( lock );
}
string s = messageQ.front();
messageQ.pop();
}
}
void produce()
{
int i = 0;
while(( !bStop ) && ( i < MESSAGE ))
{
stringstream out;
out << i;
string s = out.str();
boost::mutex::scoped_lock lock( mutexQ );
messageQ.push( s );
i++;
condQ.notify_one();
}
}