C++11: Почему переменная std::condition использует std:: unique lock?
Я немного запутался в роли std::unique_lock при работе с std::condition_variable. Насколько я понял документация,std::unique_lock в основном раздутый замок охранник, с возможностью замены состояния между двумя замками.
Я до сих пор использовать pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) для этой цели (я думаю, что это то, что STL использует на posix). Для этого нужен мьютекс, а не замок.
какая здесь разница? Тот факт, что std::condition_variable занимается std::unique_lock оптимизация? Если это так, как это быстрее?
2 ответов:
то есть технической причины нет?
я поддержал ответ cmeerw, потому что я считаю, что он дал техническую причину. Давайте пройдемся по нему. Давайте представим, что комитет решил иметь
condition_variableожиданиеmutex. Вот код, использующий этот дизайн:void foo() { mut.lock(); // mut locked by this thread here while (not_ready) cv.wait(mut); // mut locked by this thread here mut.unlock(); }именно так один не стоит использовать
condition_variable. В регионах, отмеченных:// mut locked by this thread hereсуществует проблема безопасности исключения, и это это серьезный вопрос. Если в этих областях возникает исключение (или
cv.waititself), заблокированное состояние мьютекса просачивается, если только try/catch также не помещается где-то, чтобы поймать исключение и разблокировать его. Но это просто больше кода, который вы просите программиста написать.предположим, что программист знает, как написать безопасный код исключения, и знает, как использовать
unique_lockдля ее достижения. Теперь код выглядит так:void foo() { unique_lock<mutex> lk(mut); // mut locked by this thread here while (not_ready) cv.wait(*lk.mutex()); // mut locked by this thread here }это намного лучше, но это так все еще не очень хорошая ситуация. Элемент
condition_variableинтерфейс делает программиста изо всех сил, чтобы заставить вещи работать. Существует возможное разыменование нулевого указателя, еслиlkслучайно не ссылается на мьютекс. И нет никакого способа дляcondition_variable::waitчтобы проверить, что этот поток действительно владеет блокировкой наmut.о, вспомнил, есть также опасность, что программист может выбрать неправильный
unique_lockфункция-член для предоставления мьютекса.*lk.release()было бы катастрофой здесь.теперь давайте посмотрим, как код пишется с фактическим
condition_variableAPI, который принимаетunique_lock<mutex>:void foo() { unique_lock<mutex> lk(mut); // mut locked by this thread here while (not_ready) cv.wait(lk); // mut locked by this thread here }
- этот код так прост, как он может получить.
- это исключение безопасности.
- The
это по существу решение дизайна API, чтобы сделать API максимально безопасным по умолчанию (с дополнительными накладными расходами, которые рассматриваются как незначительные). Требуя передать
unique_lockвместо rawmutexпользователи API ориентированы на написание корректного кода (при наличии исключений).в последние годы акцент языка C++ сместился в сторону обеспечения его безопасности по умолчанию (но все еще позволяет пользователям стрелять себе в ноги, если они хотят и пытаются достаточно жестко).
Comments