unique_lock详解

一、unique_lock取代lock_guard

unique_lock是个类模板,工作中,一般lock_guard(推荐使用);
lock_guard取代了mutex的lock()和unlock()。
unique_lock比lock_guard灵活很多灵活很多;效率上差一点,内存占用多一点。
std::lock_guard<std::mutex> sbguard(my_mutex);直接换成std::unique_lock<std::mutex> sbguard(my_mutex);

二、unique_lock的第二个参数

lock_guard可以带第二个参数:

std::lock_guard<std::mutex> sbguard(my_mutex,std::adopt_lock);

//adopt_lock标记作用,unique_lock也支持

2.1 std::adopt_lock:

表示这个互斥量已经被lock了(你必须提前把互斥量lock了

std::adopt_lock标记的效果就是假设调用方线程已经拥有了互斥的所有权(已经lock()成功了),通知lock_guard不需要在构造函数中lock这个互斥量了
unique_lock也可以带std::adopt_lock标记,含义相同

2.2 std::try_to_lock

【引言】
std::mutex::lock特点:
拿到锁之后立即返回,拿不到锁一直卡着。

我们会尝试用mutex的lock()去锁定这个mutex,但如果没锁定成功,我也会立即返回,并不会阻塞在那里;
用这个try_to_lock的前提是你自己不能先去lock

std::unique_lock<std::mutex> sb_guard(my_mutex1,std::try_to_lock);
 if (sb_guard.owns_lock())
{
	msgRecvQueue.push_back(i);
}
else
{
	cout << "inMsgRecvQueue()执行,但没有拿到锁,只能干点别的事" << i << endl;
}

2.1 2.2小结:
adopt_lock前提要把互斥量锁住了,try_to_lock的前提是你自己不能先去lock(只能用unique_lock调用构造函数锁)

2.3 std::defer_lock

前提是你不能自己先lock,否则会报异常。
意思是就是没有给mutex加锁,初始化了一个没有加锁的mutex。
我们借着unique_lock的话题,来介绍一些unqiue_lock的重要成员函数

std::unique_lock<std::mutex> sbguard(my_mutex1,std::defer_lock);//没有加锁的my_mutex
sbguard.lock(); //咱们不用自己unlock()

三、unique_lock的成员函数

3.1 lock()

3.2 unlock()

 std::unique_lock<std::mutex> sbguard(my_mutex1,std::defer_lock);//没有加锁的my_mutex
sbguard.lock(); //咱们不用自己unlock()

//因为有一些非共享的代码要处理
 sbguard.unlock();
//处理一些非共享代码

sbguard.lock();
msgRecvQueue.push_back(i);
sbguard.unlock();	//画蛇添足,但也可以

3.3 try_lock()

尝试给互斥量加锁,如果拿不到锁,则返回false,如果拿到了锁,返回true,这个函数不阻塞

std::unique_lock<std::mutex> sbguard(my_mutex1,std::defer_lock);//没有加锁的my_mutex
if (sbguard.try_lock() == true)
{
	msgRecvQueue.push_back(i);
}
else
{
	cout << "inMsgRecvQueue()执行,但没有拿到锁,只能干点别的事" << i << endl;
}

std::unique_lock::try_lock()std::defer_lock()配合使用

3.4 release()

返回它所管理的mutex对象指针,并释放所有权;也就是说,这个unique_lock和mutex不再有关系

严格区分unlock()和release()区别,不要混淆。

std::unique_lock<std::mutex> sbguard(my_mutex1);

相当于把unique_lock和std::mutex类对象my_mutex1绑定在一起
如果原来mutex对象处于加锁状态,你有责任接管过来并负责解锁。

std::unique_lock<std::mutex> sbguard(my_mutex1);//没有加锁的my_mutex
std::mutex* ptx = sbguard.release();
msgRecvQueue.push_back(i);
ptx->unlock();

注意:
lock锁住的代码段越少,执行越快,整个程序运行效率越高。
lock锁住的代码多少,称为锁的粒度,粒度一般用粗细来描述;
a) 锁住的代码少,这个粒度叫细。执行效率高;
b) 锁住的代码多,粒度叫粗,执行效率就低。

四、unique_lock所有权的传递

unique_lock需要和一个mutex对象绑定到一起发挥作用(配合使用、管理)
不能将一个mutex对象和两个unique_lock绑定在一起
这就是所有权的概念

std::unique_lock<std::mutex> sbguard(my_mutex1);

sbguard拥有my_mutex1的所有权
sbguard可以把自己对mutex类对象(my_mutex1)的所有权转移给其他unique_lock对象;
所以,unique_lock对象 这个mutex所有权是属于可以转移,但是不能复制。

4.1 通过std::move()转移所有权

std::unique_lock<std::mutex> sbguard(my_mutex1);
std::unique_lock<std::mutex> sbguard2(std::move(sbguard));//移动语义,现在相当于sbguard2和my_mutex1绑定到一起了,现在sbguard指向空,sbguard已经解除了my_mutex1的管理,由sbguard2接管

4.2 通过函数返回值return std::unique_lock<std::mutex>转移所有权

std::unique_lock<std::mutex> rtn_unique_lock()
{
        std::unique_lock<std::mutex> tmpguard(my_mutex1);
        return tmpguard; //从函数返回一个局部的unique_lock对象是可以的。三章14节讲过移动构造函数。
                         //返回这种局部对象tmpguard会导致系统生成临时的unique_lock对象,并调用unqiue
}
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值