Namespaces
Variants

std:: lock_guard

From cppreference.net
Concurrency support library
Threads
(C++11)
(C++20)
this_thread namespace
(C++11)
(C++11)
Cooperative cancellation
Mutual exclusion
Generic lock management
(C++11)
lock_guard
(C++11)
(C++11)
(C++11)
Condition variables
(C++11)
Semaphores
Latches and Barriers
(C++20)
(C++20)
Futures
(C++11)
(C++11)
(C++11)
Safe reclamation
Hazard pointers
Atomic types
(C++11)
(C++20)
Initialization of atomic types
(C++11) (deprecated in C++20)
(C++11) (deprecated in C++20)
Memory ordering
(C++11) (deprecated in C++26)
Free functions for atomic operations
Free functions for atomic flags
定义于头文件 <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=
[deleted]
不可复制赋值
(公开成员函数)

注释

一个常见的初学者错误是忘记为 lock_guard 变量命名,例如写成 std :: lock_guard { mtx } 。这会构造一个立即被销毁的纯右值对象,从而未能实际构造一个在作用域剩余时间内持有互斥量的锁。

std::scoped_lock lock_guard 提供了一种替代方案,具备通过死锁避免算法锁定多个互斥量的能力。

(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 提供了来自 lock_guard<Mutex> 的冗余推导指南 已移除

另请参阅

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