unique_lock详解

一、unique_lock取代lock_guard

  • unique_lock是个类模板,实际应用中,一般lock_guard(推荐使用);lock_guard取代了mutex和的lock()和nulock(), 而unique_lock也取代mutex和的lock()和nulock();
  • unique_lock比lock_guard灵活很多(多出来很多用法),效率差一点,内存占用多一点;
  • 使用:unique_lock<mutex> myUniLock(myMutex)

二、unique_lock的第二个参数

2.1 std:: adopt_lock

  • lock_guard中也可以用这个参数

  • 表示这个互斥量已经被lock(),即不需要在构造函数中lock这个互斥量了,前提:必须提前lock;

  • adopt_lock就是起一种标记作用,标志效果:“假设调用方线程已经拥有了互斥的所有权(即已经lock()成功了的);

2.2 std::try_to_lock

  • 意思:我们会尝试用mutex的lock()去锁定这个mutex,但是不同的是,如果没有锁定成功,也会立即返回,不会阻塞继续尝试锁定;
  • 搭配owns_lock()方法判断是否拿到锁,如拿到返回true,没有拿到返回false;
  • 前提:当下线程再使用该参数前,不要使用lock,不然没有意义,因为肯定拿不到;
  • 使用try_to_lock的原因:是防止其他的线程锁定mutex太长时间,导致本线程一直阻塞在lock这个地方。

例子:

//写入数据函数;
void inMsgPro() { for (int i = 0; i < 100; ++i) {
cout << "inMsgPro()执行,插入元素" << i << endl; unique_lock<mutex> myUniLock(mutex1, try_to_lock);
if (myUniLock.owns_lock() == true) {
msgRecvQueue.push(i);
}
else {
cout << "拿不到锁" << endl;
//其他操作代码
} }
}

2.3 std::defer_lock

  • 意思:加上defer_lock是初始化了一个没有加锁的mutex
  • 前提:当下线程再使用该参数前,不要使用lock,不然没有意义,逻辑相悖;
  • 使用std::defer_lock的原因:是以后可以调用unique_lock的一些方法

三、unique_lock的成员函数(前三个要与defer_lock联合使用)

3.1 lock(): 加锁

unique_lock<mutex> myUniLock(myMutex, defer_lock);
//加锁!
myUniLock.lock();
//注意:可以不用自己解锁,myUniLock对象析构的时候会进行unlock()操作;

3.2 unlock(): 解锁

unique_lock<mutex> myUniLock(myMutex, defer_lock);
myUniLock.lock();//加锁!
//处理共享数据的代码
myUniLock.unlock();//解锁!
//处理非共享数据的代码(可能很多)
//.......
myUniLock.lock();//加锁!
//处理共享数据的代码
myUniLock.unlock();//解锁!

为什么有时候需要unlock():因为lock锁住的代码越多,锁的粒度越粗,执行效率就低;反而如果我们只锁住共享的代码,锁住代码少,锁的粒度细,执行效率高!

要选这合适的粒度:不能漏掉共享数据的保护,但是也不可以将其他不必要的代码加入!

3.3 try_lock(): 尝试给互斥量加锁

  • 如果拿到锁,则返回true,如果拿不到锁,函数不阻塞,返回false,继续往下执行;

这个操作和try_to_lock操作很像,个人感觉像是在defer_lock情况下加上这种不阻塞的功能;

3.4 release():

  • unique_lock<mutex>myUniLock(myMutex);相当于把myMutex和myUniLock绑定在了一起,而release()就是解除绑定,返回它所管理的mutex对象的指针,并释放所有权,不再指向mutex对象;
  • mutex* ptx = myUniLock.release();所有权由ptx接管,如果原来mutex对象进行了加锁,处于加锁状态,就需要ptx在后面进行解锁了;
  • 注意release()和unlock()的区别,一个是释放了所有权,一个只是释放锁,该对象还是和mutex绑定着;

四、unique_lock所有权的传递

unique_lock<mutex> myUniLock(myMutex);把myMutex和myUniLock绑定在了一起,也就是myUniLock拥有myMutex的所有权

所有权转移方式:

①使用move转移:

所有权可以转移,但是不能复制!

unique_lock<mutex> myUniLock(myMutex);
//unique_lock<mutex> myUniLock2(myUniLock); //复制所有权是非法,一种拷贝构造;
unique_lock<mutex> myUniLock2(std::move(myUniLock));//移动语言,传右值,调用带右值引用的拷贝构造,将myUniLock2和myMutex绑定一起,而myUniLock指向空!

②在函数中return一个临时变量,即可以实现转移

unique_lock<mutex> rtn_unique_lock()
{
unique_lock<mutex> myUniLock(myMutex);//位置1
//移动构造函数那里讲从函数返回一个局部的unique_lock对象是可以的
//返回这种局部对象会导致系统生成临时的unique_lock对象,并调用unique_lock的移动构造函数
return myUniLock;
}
// 然后就可以在外层调用,在myUniLock2具有对myMutex的所有权
std::unique_lock<std::mutex> myUniLock2 = rtn_unique_lock();//位置2

其实这种方法的本质是:用在函数中创建临时变量(位置1),将局部临时变量拷贝一份给调用函数(位置2,这里又有一份临时变量),最后再由位置2的临时变量 赋值给myUniLock2!

可以看出,是非常消耗内存,浪费资源时间的,因为位置1、2的临时对象构造马上又析构了,后面也不会用它们。所以强烈推荐使用move转移语义调用移动构造函数!

多线程05:unique_lock详解的更多相关文章

  1. ASP.NET MVC Filters 4种默认过滤器的使用【附示例】 数据库常见死锁原因及处理 .NET源码中的链表 多线程下C#如何保证线程安全? .net实现支付宝在线支付 彻头彻尾理解单例模式与多线程 App.Config详解及读写操作 判断客户端是iOS还是Android,判断是不是在微信浏览器打开

    ASP.NET MVC Filters 4种默认过滤器的使用[附示例]   过滤器(Filters)的出现使得我们可以在ASP.NET MVC程序里更好的控制浏览器请求过来的URL,不是每个请求都会响 ...

  2. Python多线程与多进程详解

    进程,线程,协程https://blog.csdn.net/qq_23926575/article/details/76375337 多进程 https://www.cnblogs.com/lipij ...

  3. Java——多线程之方法详解

    Java多线程系列文章是Java多线程的详解介绍,对多线程还不熟悉的同学可以先去看一下我的这篇博客Java基础系列3:多线程超详细总结,这篇博客从宏观层面介绍了多线程的整体概况,接下来的几篇文章是对多 ...

  4. C++并发与多线程学习笔记--unique_lock详解

    unique_lock 取代lock_quard unique_lock 的第二个参数 std::adopt_lock std::try_to_lock std::defer_lock unique_ ...

  5. iOS GCD NSOperation NSThread等多线程各种举例详解(拷贝)

    2年多的iOS之路匆匆而过,期间也拜读来不少大神的博客,近来突然为自己一直做伸手党感到羞耻,是时候回馈社会.回想当年自己还是小白的时候,照着一些iOS多线程教程学,也只是照抄,只知其然.不知其所以然. ...

  6. iOS GCD NSOperation NSThread等多线程各种举例详解

    废话就不多说,直接上干货.如下图列举了很多多线程的知识点,每个按钮都写有对应的详细例子,并对运行结果进行分析,绝对拿实践结果来说话.如果各位道友发现错误之处还请指正.附上demo下载地址

  7. 【多线程】java多线程 测试例子 详解wait() sleep() notify() start() join()方法 等

    java实现多线程,有两种方法: 1>实现多线程,继承Thread,资源不能共享 2>实现多线程  实现Runnable接口,可以实现资源共享 *wait()方法 在哪个线程中调用 则当前 ...

  8. 在.Net框架中 C# 实现多线程的同步方法详解

    本文主要描述在C#中线程同步的方法.线程的基本概念网上资料也很多就不再赘述了.直接接入主题,在多线程开发的应用中,线程同步是不可避免的.在.Net框架中,实现线程同步主要通过以下的几种方式来实现,在M ...

  9. Java程序员必备知识-多线程框架Executor详解

    为什么引入Executor线程池框架 new Thread()的缺点 每次new Thread()耗费性能 调用new Thread()创建的线程缺乏管理,被称为野线程,而且可以无限制创建,之间相互竞 ...

随机推荐

  1. 学习ELK日志平台(一)

    一.需求及基础: 场景: 1.开发人员不能登录线上服务器查看详细日志 2.各个系统都有日志,日志数据分散难以查找 3.日志数据量大,查询速度慢,或者数据不够实时 4.一个调用会涉及到多个系统,难以在这 ...

  2. 1.时任务XXL_Job框架踩过的坑

    遇到的问题 问题1:执行器地址为空 原因-->执行器中 没有地址 解决方案-->输入地址:http://IP地址:端口 IP地址 端口 问题2:异常信息unknown code for r ...

  3. 【动态系统的建模与分析】8_频率响应_详细数学推导 G(jw)_滤波器

  4. IPhoneX网页布局简介

    IPhoneX全面屏是十分科技化的,但是由于其圆角和摄像头刘海位置以及操控黑条的存在使得我们需要去对其样式做一些适配,没有X的同学可以开启 Xcode 9 的iPhone X 模拟器作为学习和调试. ...

  5. es8(字符串,对象)

    es8(字符串,对象) 字符串补白: let str = "abc"; let a = str.padEnd(5); let b = str.padStart(5); let c ...

  6. Idea导出jar包和使用自定义API

    自定义jar简单实现案例 学习内容 1. 自定义工具类 2. 导出jar 3. 加载Jar包 4. 调用自定义的API方法 总结 学习内容 1. 自定义工具类 新建一个java项目,然后创建包和工具类 ...

  7. 《头号玩家》AI电影调研报告(二)

    四. 涉及前沿技术及与现实的交互 1.VR技术 在影片中,斯皮尔伯格用他认为未来的VR虚拟技术为我们创造了众多精彩的画面,令人佩服其对科技的预见性.其中好多的装备特别引人注目,部分也在现实中存在:VR ...

  8. Windows 10搭建FTP服务器

    1 开启FTP服务 控制面板 -> 程序和功能 -> 启用或关闭Windows功能 找到下面选项的勾选 2 添加FTP站点 在开始菜单里面输入 IIS 搜索并打开 IIS管理器 展开左侧菜 ...

  9. VScode链接服务器并配置公钥-SSH Keys

    VScode链接服务器并配置公钥-SSH Keys 一直在用Xshell做SSH连接服务器与虚拟机,但是中文乱码的问题一直找不到解决方案,干脆使用编辑器自带的插件,集成之后用起来也方便 1.概述 做法 ...

  10. DOM 对象的重点核心

    概述 :  文档对象模型(Document Object Model,简称DOM ),是W3C组织推荐的处理可扩展标记语言 (HTML或者XML)的标准编程接口. W3C已经定义了一系列的DOM接口, ...