Подтвердить что ты не робот

Std:: lock_guard или std:: scoped_lock?

В С++ 17 был введен новый класс блокировки std::scoped_lock.

Судя по документации, она похожа на уже существующий класс std::lock_guard.

Какая разница и когда я должен его использовать?

4b9b3361

Ответ 1

Единственное и важное отличие состоит в том, что 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 которую можно увидеть здесь.

Для получения дополнительной информации вы можете прочитать стандартную статью

Ответ 2

scoped_lock является строго лучшей версией lock_guard, которая блокирует произвольное количество мьютексов одновременно (используя тот же алгоритм устранения взаимоблокировок как std::lock). В новом коде вы должны использовать только scoped_lock.

Единственная причина, по которой существует lock_guard, - это совместимость. Его нельзя просто удалить, поскольку он используется в текущем коде. Более того, оказалось нежелательным изменить свое определение (от унарного до вариационного), потому что это также наблюдаемое и, следовательно, нарушение, изменяется (но по некоторым техническим причинам).

Ответ 3

Вот образец и цитата из 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, с меньшим потенциалом для ошибок, что может быть только хорошим вещь!