поэтому нет технической причины?
Я поддержал ответ 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.wait
), заблокированное состояние мьютекса просачивается, если попытка 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
, чтобы выставить мьютексы. был бы катастрофическим.
Теперь давайте посмотрим на то, как код написан с фактическим condition_variable
API, который принимает 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
}
- Этот код так же просто, как он может получить.
- Это исключение.
- Функция
wait
может проверять lk.owns_lock()
и выдавать исключение, если оно false
.
Это технические причины, по которым дизайн API condition_variable
.
Кроме того, condition_variable::wait
не займет lock_guard<mutex>
lock_guard<mutex>
, потому что, как вы говорите: у меня есть замок на этом мьютекса до lock_guard<mutex>
Уничтожает. Но когда вы вызываете condition_variable::wait
, вы неявно освобождаете блокировку на мьютексе. Таким образом, действие несовместимо с оператором использования/.
Нам нужно unique_lock
все равно так, что можно было бы вернуть замки из функций, поместите их в контейнеры, и блокировка/разблокировка мьютексы в не контекстными узорами в исключительных безопасным способом, так unique_lock
был естественным выбором для condition_variable::wait
.
Update
bamboon предложил в комментариях ниже, что я противоположность condition_variable_any
, так что здесь идет:
Вопрос: Почему не condition_variable::wait
шаблонных, так что я могу передать любой тип Lockable
к нему ?
Ответ:
Это действительно здорово функциональность, чтобы иметь. Например, this paper демонстрирует код, ожидающий shared_lock
(rwlock) в режиме совместного использования при переменной состояния (что-то неслыханное в мире posix, но очень полезно, тем не менее). Однако функциональность более дорогая.
Так комитет ввел новый тип с этой функциональностью:
`condition_variable_any`
С этим condition_variable
адаптером можно ждать любого заперты. Если у него есть члены lock()
и unlock()
, вам нужно идти. Для правильной реализации condition_variable_any
требуется элемент данных condition_variable
и элемент данных shared_ptr<mutex>
.
Поскольку эта новая функциональность более дорогая, чем ваша базовая condition_variable::wait
, а потому, что condition_variable
- такой инструмент низкого уровня, эта очень полезная, но более дорогая функциональность была помещена в отдельный класс, так что вы платите только за нее, если используете ее ,
Вы смущены тем, почему вам нужна блокировка/мьютекс с переменной состояния или разница между блокировкой и мьютексом или о том, почему переменная условия использует уникальный замок, а не мьютекс? – Brady
«почему переменная условия использует уникальный замок, а не мьютекс». –