std::lock_guard

1. std::lock_guard

std::lock_guard 是 C++ 标准库中的一个类模板,位于 <mutex> 头文件中。它提供了一种便利的 RAII(资源获取即初始化)机制,确保在进入作用域时锁定互斥锁,在退出作用域时解锁互斥锁,从而避免了手动管理互斥锁的复杂性和可能的错误。

其作用主要有两个方面:

  1. 自动加锁和解锁std::lock_guard 在构造时会锁定给定的互斥锁,并在析构时释放互斥锁。这意味着,无论通过正常执行还是通过异常退出,互斥锁都会被正确地释放。

  2. 防止死锁std::lock_guard 的设计有助于避免由于忘记释放互斥锁而导致的死锁问题。因为 std::lock_guard 是根据作用域来管理锁的生命周期的,它确保在作用域结束时释放锁,因此减少了手动管理锁的需求,从而减少了出错的可能性。

2. 源码剖析

_EXPORT_STD template <class _Mutex>
class _NODISCARD_LOCK lock_guard { // class with destructor that unlocks a mutex
public:
	// 使用 mutex_type 作为互斥锁类型别名
    using mutex_type = _Mutex;
	
	// 构造函数,接受一个互斥锁的引用作为参数,并在构造时锁定该互斥锁
    explicit lock_guard(_Mutex& _Mtx) : _MyMutex(_Mtx) { // construct and lock
        _MyMutex.lock();
    }
    // 构造函数,接受一个互斥锁的引用和一个`adopt_lock_t`类型的参数。这个构造函数不会锁定互斥锁,而是假设调用者已锁定互斥锁
    lock_guard(_Mutex& _Mtx, adopt_lock_t) noexcept // strengthened
        : _MyMutex(_Mtx) {} // construct but don't lock
       
	// 析构函数,会在对象被销毁时解锁互斥锁
    ~lock_guard() noexcept {
        _MyMutex.unlock();
    }
	// 禁用了拷贝构造函数和赋值运算符,以确保不能通过拷贝或赋值的方式进行对象的复制或赋值,
	// 这是因为拷贝或赋值的话会产生不可预测的行为,可能导致重复解锁已经被解锁的互斥锁。
    lock_guard(const lock_guard&)            = delete;
    lock_guard& operator=(const lock_guard&) = delete;

private:
    _Mutex& _MyMutex;
};

此外,这段代码使用了noexcept关键字来声明不会抛出异常的函数,这是一种优化的技术,有助于编译器生成更加高效的代码。

3.示例

#include <iostream>
#include <thread>
#include <mutex>


int g_i = 0;
std::mutex g_i_mutex;  // 保护 g_i

void safe_increment()
{

    std::lock_guard<std::mutex> lock(g_i_mutex);
    ++g_i;

    std::cout << std::this_thread::get_id() << ": " << g_i << '\n';
    // g_i_mutex 在锁离开作用域时自动释放
}

int main()
{

    std::cout << "main: " << g_i << '\n';

    std::thread t1(safe_increment);
    std::thread t2(safe_increment);

    t1.join();
    t2.join();

    std::cout << "main: " << g_i << '\n';
}

safe_increment() 函数中,std::lock_guard<std::mutex> 对象 lock 在函数体内被创建,它会自动锁定 g_i_mutex。当函数执行完成时,lock 对象离开作用域,会自动解锁 g_i_mutex。这样就确保了 ++g_i 这个临界区内的代码只会被一个线程执行,从而避免了竞态条件。

输出结果:

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值