std:: lock_guard
|
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Member functions | ||||
|
Определено в заголовочном файле
<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
, опционально блокируя указанный мьютекс
(public member function) |
|
уничтожает объект
lock_guard
, разблокирует базовый мьютекс
(public member function) |
|
|
operator=
[deleted]
|
не копируемый оператор присваивания
(public member function) |
Примечания
Распространённая ошибка начинающих — забыть дать переменной
lock_guard
имя, например, написав
std
::
lock_guard
{
mtx
}
. Это создаёт prvalue-объект, который немедленно уничтожается, фактически не создавая блокировку, удерживающую мьютекс до конца области видимости.
|
std::scoped_lock
предоставляет альтернативу для
|
(since C++17) |
Пример
Демонстрирует безопасное и небезопасное инкрементирование volatile переменной двумя потоками.
#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 |
предоставлялся избыточный deduction guide из
lock_guard<Mutex>
|
удалён |
Смотрите также
|
(C++11)
|
реализует перемещаемую обёртку владения мьютексом
(class template) |
|
(C++17)
|
RAII-обёртка для нескольких мьютексов, предотвращающая взаимоблокировки
(class template) |