细谈lock_guard与shared_lock与unique_lock的区别

C++互斥锁(互斥量)封装在Mutex类中,每个线程在对资源操作前都尝试先加锁,成功加锁才能操作,操作结束解锁。同一时刻,只能有一个线程持有该锁。
在这里插入图片描述
互斥锁通过调用类成员函数lock()与unlock()来实现加锁和解锁操作。
读写锁也叫做“共享-独占锁”,当读写锁以读模式锁住时,它是以共享模式锁住的;当它以写模式锁住时,它是以独占模式锁住的。当读写锁处于写加锁状态时,在其解锁之前,所有尝试对其加锁的线程都会被阻塞;
当读写锁处于读加锁状态时,所有试图以读模式对其加锁的线程都可以得到访问权,但是如果想以写模式对其加锁,线程将阻塞。
1、lock_guard:
(1)创建即加锁,作用域结束自动析构解锁,无需手工解锁。
(2)且不能中途解锁,必须等作用域结束才能解锁。
(3)缺点在于在定义lock_guard的地方会调用构造函数加锁,在离开定义域时lock_guard就会被销毁,调用析构函数解锁。如果定义域范围很大的话,锁的粒度就会很大,影响效率。
2、unique_lock
当一个函数内部有两段代码需要保护时,这个时候使用lock_guard就需要创建两个局部对象来管理一个同斥锁,修改方法是使用unique_lock,它提供lock()和unlock()接口,能记录现在是处于上锁还是未上锁状态。
std::unique_lock<std:mutex>guard(_mu);
guard.unlock();//临时解锁
guard.lock(); //临时上锁
而unique_lock在析构的时候会判断当前锁的状态来决定是否解锁,如果已经是解锁状态了,就不会再次解锁了,效率较慢。unique_lock是write lock。被锁后不允许其他线程执行被shared_lock或unique_lock的代码。
3、shared_lock可用于保护共享数据不被多个线程同时访问。std::shared_lock::lock
以共享模式锁定关联互斥。等效于调用 mutex.lock_shared();用于获得互斥的共享所有权。若另一线程以排他性所有权保有互斥,则到 lock_shared 的调用将阻塞执行,直到能取得共享所有权。shared_lock是read lock。被锁后仍允许其他线程执行同样被shared_lock的代码。这是一般做读操作时的需要。
4、std:adopt_lock称为自适应锁,用于判断。表示可传递给lock_guard和unique_lock的构造函数,假设调用一方已经lock成功了,则通知lock_guard不需要再构造函数中lock这个互斥量了(就是不需要再锁了)。

  • 6
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
lock_guardunique_lockC++11中的两种线程安全定方式,它们都是用来保护共享资源的,但它们的实现方式略有不同。 lock_guard源码: ```c++ template<typename _Mutex> class lock_guard { public: typedef _Mutex mutex_type; //构造函数,定互斥量 explicit lock_guard(mutex_type& __m) : _M_device(__m) { _M_device.lock(); } //析构函数,释放互斥量 ~lock_guard() { _M_device.unlock(); } //禁止拷贝构造函数和赋值操作符 lock_guard(const lock_guard&) = delete; lock_guard& operator=(const lock_guard&) = delete; private: mutex_type& _M_device; }; ``` 在lock_guard的构造函数中,它会定传入的互斥量。在lock_guard的析构函数中,它会释放互斥量。这样,在lock_guard对象的生命周期中,只要它存在,它所定的互斥量就不会被其他线程所访问。 unique_lock源码: ```c++ template<typename _Mutex> class unique_lock { public: typedef _Mutex mutex_type; //构造函数 unique_lock() noexcept : _M_device(0), _M_owns(false) { } explicit unique_lock(mutex_type& __m) noexcept : _M_device(std::addressof(__m)), _M_owns(true) { _M_device->lock(); } unique_lock(mutex_type& __m, defer_lock_t) noexcept : _M_device(std::addressof(__m)), _M_owns(false) { } unique_lock(mutex_type& __m, adopt_lock_t) noexcept : _M_device(std::addressof(__m)), _M_owns(true) { } template<typename _Clock, typename _Duration> unique_lock(mutex_type& __m, const chrono::time_point<_Clock, _Duration>& __t) : _M_device(std::addressof(__m)), _M_owns(false) { const auto __now = _Clock::now(); if (__now < __t) { const auto __d = chrono::duration_cast<chrono::milliseconds>(__t - __now); if (_M_device->try_lock_for(__d)) _M_owns = true; } } template<typename _Rep, typename _Period> unique_lock(mutex_type& __m, const chrono::duration<_Rep, _Period>& __d) : _M_device(std::addressof(__m)), _M_owns(false) { if (_M_device->try_lock_for(__d)) _M_owns = true; } //析构函数 ~unique_lock() noexcept { if (_M_owns) _M_device->unlock(); } //加 void lock() { if (!_M_owns) { _M_device->lock(); _M_owns = true; } } //尝试加 bool try_lock() { if (!_M_owns && _M_device->try_lock()) { _M_owns = true; return true; } return false; } //解 void unlock() { if (_M_owns) { _M_device->unlock(); _M_owns = false; } } //释放定的互斥量 mutex_type* release() noexcept { mutex_type* __t = _M_device; _M_device = 0; _M_owns = false; return __t; } //获取定的互斥量 mutex_type* mutex() const noexcept { return _M_device; } //获取定状态 bool owns_lock() const noexcept { return _M_owns; } //禁止拷贝构造函数和赋值操作符 unique_lock(const unique_lock&) = delete; unique_lock& operator=(const unique_lock&) = delete; private: mutex_type* _M_device; bool _M_owns; }; ``` unique_lock相对于lock_guard有更多的构造函数,可以更灵活地操作互斥量。unique_lock的默认构造函数和defer_lock_t构造函数不会定互斥量,而adopt_lock_t构造函数会假设当前线程已经定互斥量,直接使用。unique_lock还提供了try_lock、unlock、release等成员函数,可以更方便地操作互斥量。 总之,lock_guardunique_lock的实现方式不同,但它们都可以用来保护共享资源的线程安全。在实际使用中,需要根据需求灵活选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值