命名空间
变体
操作

std::lock_guard

来自 cppreference.cn
< cpp‎ | thread
 
 
并发支持库
线程
(C++11)
(C++20)
this_thread 命名空间
(C++11)
(C++11)
(C++11)
协作式取消
互斥
(C++11)
通用锁管理
(C++11)
lock_guard
(C++11)
(C++11)
(C++11)
(C++11)
条件变量
(C++11)
信号量
闩锁和屏障
(C++20)
(C++20)
期物
(C++11)
(C++11)
(C++11)
(C++11)
安全回收
(C++26)
Hazard 指针
原子类型
(C++11)
(C++20)
原子类型的初始化
(C++11)(C++20 中已弃用)
(C++11)(C++20 中已弃用)
内存顺序
(C++11)(C++26 中已弃用)
用于原子操作的自由函数
用于原子标志的自由函数
 
 
定义于头文件 <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); (这会默认构造一个名为 mtxlock_guard 变量) 或 std::lock_guard{mtx}; (这会构造一个立即销毁的纯右值对象),因此实际上并没有构造一个在作用域的剩余时间内持有互斥量的锁。

std::scoped_locklock_guard 提供了一个替代方案,该方案提供了使用死锁避免算法锁定多个互斥量的能力。

(自 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> 的冗余推导指引 已移除

[编辑] 参见

实现可移动的互斥量所有权包装器
(类模板) [编辑]
用于多个互斥量的避免死锁的 RAII 包装器
(类模板) [编辑]