Подтвердить что ты не робот

Почему 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;
   }
}

Спасибо!

4b9b3361

Ответ 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, однако вы должны использовать условие или даже лучше барьер.