std::lock_guard
来自 cppreference.cn
定义于头文件 <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); (这会默认构造一个名为 mtx
的 lock_guard
变量) 或 std::lock_guard{mtx}; (这会构造一个立即销毁的纯右值对象),因此实际上并没有构造一个在作用域的剩余时间内持有互斥量的锁。
std::scoped_lock 为 |
(自 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 | 提供了来自 lock_guard<Mutex> 的冗余推导指引 |
已移除 |
[编辑] 参见
(C++11) |
实现可移动的互斥量所有权包装器 (类模板) |
(C++17) |
用于多个互斥量的避免死锁的 RAII 包装器 (类模板) |