unique_lock详解

unique_lock取代lock_guard

unique_lock是一个类模板,比lock_guard更加灵活,效率上低一点,内存占用大一点
首先是unique_lock可以直接替换lock_guard,调用unique_lock也不需要手动解锁

std::lock_guard<std::mutex>myguard1(my_mutex1);

   
   
  • 1

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

   
   
  • 1

的效果是一样的。

unique_lock可以带第二个参数

unique_lock的第二个参数

std::adopt_lock

unique_lock和lock_guard的adopt_lock参数含义相同
表示互斥量已经被lock了(必须要把互斥量提前lock,否则会报异常
效果就是该线程已经拥有了互斥量的所有权(已经lock成功),通知lock_guard不需要在构造函数中lock这个互斥量

std::try_to_lock

std::unique_lock<std::mutex>myguard1(my_mutex1, std::try_to_lock);

   
   
  • 1

执行过这句话之后(在这句话之前不能先使用lock),我们通过owns_lock()判断来进行下一步操作,不会卡在此处,如果其他线程持续占用该互斥量锁,那么该线程就不会持续等待。

std::unique_lock<std::mutex>myguard1(my_mutex1,std::try_to_lock);
if (myguard1.owns_lock())
{
	cout << "inMsgRecvQueue执行插入一个元素" << i << endl;
	msgRecvQueue.push_back(i);
}
else
{
	cout << "inMsgRecvQueue执行了,但是没有拿到锁\n" << i << endl;
}

   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

std::defer_lock

作用是初始化一个没有加锁的mutex(在使用其他参数时会在创建mutex时直接尝试加锁)
可以借着defer_lock来介绍一些unique_lock的成员函数

unique_lock的成员函数

成员函数lock()

std::unique_lock<std::mutex>myunique_lock(my_mutex1,std::defer_lock);//创建一个没有加锁的myunique_lock
myunique_lock.lock();//对myunique_lock进行加锁操作

   
   
  • 1
  • 2

对于没有加锁的myunique_lock,可以通过成员函数myunique_lock.lock()进行上锁。

成员函数unlock()

对于上锁的myunique_lock,可以通过unlock()提前解锁来运行一些不需要共享数据的代码,这使得我们的代码设计更加灵活。

std::unique_lock<std::mutex>myunique_lock(my_mutex1,std::defer_lock);//创建一个没有加锁的myunique_lock
myunique_lock.lock();//对myunique_lock进行加锁操作
//处理一些共享数据代码
myunique_lock.unlock();
//继续处理一些非共享代码
//。。。。。。
//处理完之后可以再次上锁
myunique_lock.lock();//对myunique_lock进行加锁操作

   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

为什么要使用unlock():
有人也把锁头锁住的代码多少称为锁的粒度,粒度一般用粗细来描述

  • 锁住的代码越少,这个锁的粒度就细,执行效率就越高
  • 锁住的代码越多,这个锁的粒度就粗,执行效率就越低
    要选择合适粒度的代码来上锁!

成员函数try_lock()

类似于参数std::try_to_lock,在不阻塞的情况下进行lock,如果加锁成功,那么返回true,如果没有加锁成功,那么返回false。

std::unique_lock<std::mutex>myunique_lock(my_mutex1,std::defer_lock);//创建一个没有加锁的myunique_lock
if(myunique_lock.try_lock())
{
	//上锁成功,进行数据处理
}

   
   
  • 1
  • 2
  • 3
  • 4
  • 5

成员函数release()

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

要区分开release()和unlock()。

release()之后要负责把上锁的mutex解锁,否则会报错。

std::unique_lock<std::mutex>myunique_lock(my_mutex1,std::defer_lock);//创建一个没有加锁的myunique_lock
myunique_lock.lock();//对myunique_lock进行加锁操作
//处理一些共享数据代码
std::mutex *ptr = myunique_lock.release();//释放myunique_lock并返回my_mutex1的指针
//处理共享数据
ptr->unlock();//手动解锁,如果不解锁会卡住导致程序崩溃

   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

unique_lock所有权的传递(转移)

一般来说,unique_lock和mutex是绑定在一起的,是通过unique_lock来管理mutex。

所有权概念

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

   
   
  • 1

表示myunique_lock拥有my_mutex1的所有权,可以把该所有权转移给其他的unique_lock对象。
可以通过move来转移所有权

std::unique_lock<std::mutex>myunique_lock(my_mutex1,std::defer_lock);//创建一个没有加锁的myunique_lock
std::unique_lock<std::mutex>myunique_lock2(std::move(myunique_lock));//将myunique_lock所有的my_mutex1转移给myunique_lock2

   
   
  • 1
  • 2

也可以通过return来返回unique_lock

std::unique_lock<std::mutex> rtn_unique_lock()
{
	std::unique_lock<std::mutex> tmpguard(my_mutex1);
	return tmpguard;//从函数返回一个局部的unique_lock对象是可以的
					//返回这种局部对象tmpguard会导致系统生成临时的unique_lock对象,并调用unique_lock的移动构造函数
}

   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

然后调用这个rtn_unique_lock()函数来转移移动构造函数的所有权

std::unique_lock<std::mutex> myunique_lock2 = rtn_unique_lock();

   
   
  • 1

此时myunique_lock2 就是互斥量my_mutex1的一个unique_lock对象。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值