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 оптимизация? Если это так, как это быстрее?

614   2  

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.wait itself), заблокированное состояние мьютекса просачивается, если только 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_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
}
  1. этот код так прост, как он может получить.
  2. это исключение безопасности.
  3. The

это по существу решение дизайна API, чтобы сделать API максимально безопасным по умолчанию (с дополнительными накладными расходами, которые рассматриваются как незначительные). Требуя передать unique_lock вместо raw mutex пользователи API ориентированы на написание корректного кода (при наличии исключений).

в последние годы акцент языка C++ сместился в сторону обеспечения его безопасности по умолчанию (но все еще позволяет пользователям стрелять себе в ноги, если они хотят и пытаются достаточно жестко).

Comments

    Ничего не найдено.