Spec-Zone.ru › C++

std::lock_guard

Определено в заголовке <mutex>
template< class Mutex >
class lock_guard;
(с C++11)

Класс lock_guard — это обёртка над мьютексом, предоставляющая удобный механизм RAII для владения мьютексом на протяжении блока кода.

При создании объекта lock_guard, он пытается получить владение мьютексом. Когда управление выходит за пределы области, в которой был создан объект lock_guard, объект lock_guard уничтожается и мьютекс освобождается.

Класс lock_guard не может быть скопирован.

Параметры шаблона

Mutex - тип мьютекса для блокировки. Тип должен удовлетворять требованиям BasicLockable

Типы членов

Тип члена Определение
mutex_type Mutex

Члены-функции

(конструктор)
конструктор объекта lock_guard, необязательно блокирует заданный мьютекс
(публичный член-функция)
(деструктор)
деструктор объекта lock_guard , разблокирует базовый мьютекс
(публичный член-функция)
operator=
[удалено]
не может быть присвоено копированием
(публичный член-функция)

Примечания

Распространённая ошибка начинающих — забыть дать имя переменной lock_guard, например, std::lock_guard(mtx); (которая по умолчанию создаёт переменную lock_guard с именем mtx) или std::lock_guard{mtx}; (которая создаёт временный объект, который сразу же уничтожается), тем самым не создавая блокировку, удерживающую мьютекс в течение всего срока действия.

std::scoped_lock предлагает альтернативу для lock_guard , предоставляющую возможность блокировки нескольких мьютексов с помощью алгоритма избегания тупиковых ситуаций.

(с C++17)

Пример

Демонстрирует безопасное и небезопасное увеличение целочисленной переменной с помощью двух потоков.

#include <iostream>
#include <mutex>
#include <string_view>
#include <syncstream>
#include <thread>
 
volatile int g_i = 0;
std::mutex g_i_mutex;  // protects g_i
 
void safe_increment(int iterations)
{
    const std::lock_guard<std::mutex> lock(g_i_mutex);
    while (iterations-- > 0)
        g_i = g_i + 1;
    std::cout << "thread #" << std::this_thread::get_id() << ", g_i: " << g_i << '\n';
 
    // g_i_mutex is automatically released when lock goes out of scope
}
 
void unsafe_increment(int iterations)
{
    while (iterations-- > 0)
        g_i = g_i + 1;
    std::osyncstream(std::cout) << "thread #" << std::this_thread::get_id()
                                << ", g_i: " << g_i << '\n';
}
 
int main()
{
    auto test = [](std::string_view fun_name, auto fun)
    {
        g_i = 0;
        std::cout << fun_name << ":\nbefore, g_i: " << g_i << '\n';
        {
            std::jthread t1(fun, 1'000'000);
            std::jthread t2(fun, 1'000'000);
        }
        std::cout << "after, g_i: " << g_i << "\n\n";
    };
    test("safe_increment", safe_increment);
    test("unsafe_increment", unsafe_increment);
}

Возможный вывод:

safe_increment:
before, g_i: 0
thread #140121493231360, g_i: 1000000
thread #140121484838656, g_i: 2000000
after, g_i: 2000000
 
unsafe_increment:
before, g_i: 0
thread #140121484838656, g_i: 1028945
thread #140121493231360, g_i: 1034337
after, g_i: 1034337

Отчёты об ошибках

Следующие отчёты об ошибках, изменяющие поведение, были применены ретроактивно к ранее опубликованным стандартам C++.

DR Применено к Поведение, опубликованное Корректное поведение
LWG 2981 C++17 лишнее руководство по выводу из lock_guard<Mutex> было предоставлено удалено

См. также

unique_lock
(C++11)
реализует обёртку для перемещаемого владения мьютексом
(шаблон класса)
scoped_lock
(C++17)
обёртка RAII для блокировки нескольких мьютексов, предотвращающая тупиковые ситуации
(шаблон класса)

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/thread/lock_guard

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API