В чем заключается работа std::unique_lock при использовании с std::conditional_variable::wait()
Я совершенно запутался с необходимостью std::unique_lock
когда ждать std::conditional_variable
, Поэтому я изучаю код библиотеки в VS 2013 и запутываюсь. Вот как std::conditional_variable::wait()
внедрено:
void wait(unique_lock<mutex>& _Lck)
{ // wait for signal
_Cnd_waitX(&_Cnd, &_Lck.mutex()->_Mtx);
}
Это какая-то шутка? Завернуть мьютекс в unique_lock и ничего не делать, кроме как вернуть его позже? Почему бы просто не использовать мьютекс в списке параметров?
2 ответа
Идея в том, что когда вы звоните wait
, вы хотите получить сигнал при изменении значения некоторой переменной (отсюда condition_variable
). Теперь, поскольку вы обращаетесь к рассматриваемой переменной из нескольких потоков (иначе вам не понадобится синхронизация), она, вероятно, будет защищена мьютексом. Таким образом, пока вы ждете изменения переменной, вам придется отказаться от мьютекса, а когда вы получите сигнал, вы должны снова его получить. Это то, что эта функция делает для вас.
Проблема в том, что когда вы просыпаетесь после получения сигнала, вам нужно уже заблокировать мьютекс. Если вы попытаетесь заблокировать мьютекс после пробуждения по сигналу, вы получите состояние гонки. С другой стороны, ожидание условной переменной не может заблокировать этот мьютекс сам по себе, так как он не сможет правильно вернуть блокировку вам, и обычно вы должны заблокировать мьютекс, прежде чем вы все равно попадете в ожидание.