В С++ 17 был введен новый класс блокировки std::scoped_lock
.
Судя по документации, она похожа на уже существующий класс std::lock_guard
.
Какая разница и когда я должен его использовать?
В С++ 17 был введен новый класс блокировки std::scoped_lock
.
Судя по документации, она похожа на уже существующий класс std::lock_guard
.
Какая разница и когда я должен его использовать?
Единственное и важное отличие состоит в том, что std::scoped_lock
имеет конструктор с переменным числом аргументов, который принимает более одного мьютекса. Это позволяет заблокировать несколько взаимных блокировок в тупике, избегая так, как если бы использовался std::lock
.
{
// safely locked as if using std::lock
std::scoped_lock<std::mutex, std::mutex> lock(mutex1, mutex2);
}
Ранее вам нужно было немного потанцевать, чтобы безопасно заблокировать несколько мьютексов, используя std::lock
как объяснялось в этом ответе.
Добавление блокировки области действия упрощает использование и позволяет избежать связанных с этим ошибок. Вы можете считать std::lock_guard
устаревшим. Случай с одним аргументом std::scoped_lock
может быть реализован как специализация, поэтому вам не нужно опасаться возможных проблем с производительностью.
GCC 7 уже имеет поддержку std::scoped_lock
которую можно увидеть здесь.
Для получения дополнительной информации вы можете прочитать стандартную статью
scoped_lock
является строго лучшей версией lock_guard
, которая блокирует произвольное количество мьютексов одновременно (используя тот же алгоритм устранения взаимоблокировок как std::lock
). В новом коде вы должны использовать только scoped_lock
.
Единственная причина, по которой существует lock_guard
, - это совместимость. Его нельзя просто удалить, поскольку он используется в текущем коде. Более того, оказалось нежелательным изменить свое определение (от унарного до вариационного), потому что это также наблюдаемое и, следовательно, нарушение, изменяется (но по некоторым техническим причинам).
Вот образец и цитата из C++ Параллелизм в действии:
friend void swap(X& lhs, X& rhs)
{
if (&lhs == & rhs)
return;
std::lock(lhs.m, rhs.m);
std::lock_guard<std::mutex> lock_a(lhs.m, std::adopt_lock);
std::lock_guard<std::mutex> lock_b(rhs.m, std::adopt_lock);
swap(lhs.some_detail, rhs.some_detail);
}
против
friend void swap(X& lhs, X& rhs)
{
if (&lhs == &rhs)
return;
std::scoped_lock guard(lhs.m, rhs.m);
swap(lhs.some_detail, rhs.some_detail);
}
Существование
std::scoped_lock
означает, что большинство случаев, когда вы использовали быstd::lock
до C++ 17, теперь могут быть написаны с использованиемstd::scoped_lock
, с меньшим потенциалом для ошибок, что может быть только хорошим вещь!