Почему Boost scoped_lock не отпирает мьютексы?
Я использовал boost::mutex::scoped_lock
следующим образом:
void ClassName::FunctionName()
{
{
boost::mutex::scoped_lock scopedLock(mutex_);
//do stuff
waitBoolean=true;
}
while(waitBoolean == true ){
sleep(1);
}
//get on with the thread activities
}
В основном он устанавливает waitBoolean, а другой поток сигнализирует, что это делается, устанавливая waitBoolean в false;
Это, похоже, не работает, потому что другой поток не может получить блокировку на mutex_!!
Я предполагал, что, завернув scoped_lock в скобки, я бы прекратил его блокировку. Это не так? Чтение в Интернете говорит о том, что он только отбрасывает мьютекс при вызове деструктора. Разве это не будет уничтожено, если оно выходит из этого локального масштаба?
Сигнальная часть кода:
while(running_){
boost::mutex::scoped_lock scopedLock(mutex_);
//Run some function that need to be done...
if(waitBoolean){
waitBoolean=false;
}
}
Спасибо!
Ответы
Ответ 1
Scoped_lock действительно должен быть выпущен в конце области действия. Однако вы не блокируете waitBoolean, когда вы зацикливаете на нем, предлагая вам не защищать его должным образом и в других местах. где он установлен на false, и вы закончите неприятные условия гонки.
Я бы сказал, что вы должны использовать boost:: condition_variable, чтобы делать такие вещи, а не спать + проверять небезопасную проверку.
Ответ 2
Для синхронизации двух потоков используется переменная условия. Это современный способ синхронизации двух потоков так, как вы хотите:
Используя boost, ожидающая часть выглядит примерно так:
void BoostSynchronisationPoint::waitSynchronisation()
{
boost::unique_lock<boost::mutex> lock(_mutex);
_synchronisationSent = false;
while(!_synchronisationSent)
{
_condition.wait(lock); // unlock and wait
}
}
Часть уведомлений выглядит примерно так:
void BoostSynchronisationPoint::sendSynchronisation()
{
{
boost::lock_guard<boost::mutex> lock(_mutex);
_synchronisationSent = true;
}
_condition.notify_all();
}
Бизнес с _synchronisationSent должен избегать сильных пробуждений: см. wikipedia
Ответ 3
Также я бы предложил пометить как volatile, что waitBoolean, однако вы должны использовать условие или даже лучше барьер.