C ++ 17 ввел новый класс блокировки под названием std::scoped_lock
.
Судя по документации, он похож на уже существующий std::lock_guard
класс.
Какая разница и когда я должен его использовать?
источник
C ++ 17 ввел новый класс блокировки под названием std::scoped_lock
.
Судя по документации, он похож на уже существующий std::lock_guard
класс.
Какая разница и когда я должен его использовать?
Это scoped_lock
строго улучшенная версия, lock_guard
которая блокирует произвольное количество мьютексов одновременно (используя тот же алгоритм предотвращения тупиков, что и std::lock
). В новом коде вы должны только когда-либо использовать scoped_lock
.
Единственная причина lock_guard
все еще существует для совместимости. Его нельзя просто удалить, поскольку он используется в текущем коде. Более того, оказалось нежелательным менять свое определение (с унарного на вариационное), потому что это также наблюдаемое и, следовательно, разрушительное изменение (но по некоторым техническим причинам).
lock_guard
. Но это, безусловно, делает классы охраны немного проще в использовании.Единственное и важное отличие состоит в том, что
std::scoped_lock
в конструкторе с переменными числами используется более одного мьютекса. Это позволяет заблокировать несколько взаимных блокировок в тупик, избегая так, как если бы ониstd::lock
были использованы.Ранее вам нужно было немного потанцевать, чтобы безопасно заблокировать несколько мьютексов, используя,
std::lock
как объяснялось в этом ответе .Добавление блокировки области упрощает использование и позволяет избежать связанных с этим ошибок. Вы можете считать
std::lock_guard
устаревшим. Случай с одним аргументомstd::scoped_lock
может быть реализован как специализация, поэтому вам не нужно опасаться возможных проблем с производительностью.GCC 7 уже имеет поддержку,
std::scoped_lock
которую можно увидеть здесь .Для получения дополнительной информации вы можете прочитать стандартную статью
источник
scoped_lock lk; // locks all mutexes in scope
. LGTM.scoped_lock lk;
это новое сокращение дляscoped_lock<> lk;
. Там нет ни одного мьютексов. Значит ты прав. ;-)Поздний ответ, и в основном в ответ на:
В общем случае, когда нужно заблокировать ровно один мьютекс,
std::lock_guard
есть API, который немного безопаснее в использовании, чемscoped_lock
.Например:
Приведенный выше фрагмент, скорее всего, является случайной ошибкой во время выполнения, поскольку он компилируется, а затем абсолютно ничего не делает. Кодер, вероятно, имел в виду:
Теперь он блокирует / разблокирует
mut
.Если
lock_guard
вместо этого в двух приведенных выше примерах использовался первый пример, то это ошибка времени компиляции, а не ошибка времени выполнения, а второй пример имеет ту же функциональность, что и используемая версияscoped_lock
.Поэтому мой совет - использовать самый простой инструмент для работы:
lock_guard
если вам нужно заблокировать ровно 1 мьютекс для всей области видимости.scoped_lock
если вам нужно заблокировать несколько мьютексов, которые не точно 1.unique_lock
если вам нужно разблокировать в рамках блока (который включает в себя использование сcondition_variable
).Этот совет вовсе не означает , что
scoped_lock
должен быть переработан , чтобы не принимать 0 семафоров. Существуют допустимые случаи использования, в которых желательноscoped_lock
принимать пакеты параметров вариабельного шаблона, которые могут быть пустыми. И пустой корпус не должен ничего блокировать.И именно поэтому
lock_guard
не считается устаревшим.scoped_lock
иunique_lock
может быть расширенным набором функцийlock_guard
, но этот факт является обоюдоострым мечом. Иногда так же важно, что тип не будет делать (конструкция по умолчанию в этом случае).источник
Вот пример и цитата из C ++ Concurrency in Action :
против
источник