C++11并发与多线程笔记(6) unique_lock(类模板)

C++11并发与多线程笔记(6) unique_lock(类模板)

  • 1、unique_lock取代lock_guard
  • 2、unique_lock的第二个参数
    • 2.1 std::adopt_lock:
    • 2.2 std::try_to_lock:
    • 2.3 std::defer_lock:
  • 3、unique_lock的成员函数(前三个与std::defer_lock联合使用)
    • 3.1 lock():加锁。
    • 3.2 unlock():解锁。
    • 3.3 try_lock():尝试给互斥量加锁
    • 3.4 release():
  • 4.unique_lock所有权的传递
    • 4.1 使用move转移
    • 4.2. 在函数中return一个临时变量,也可以实现转移

1、unique_lock取代lock_guard

unique_lock 是一个类模板。
unique_lock 比 lock_guard 灵活很多多出来很多用法),效率差一点,内存占用多一些。
使用:
unique_lock<mutex> myUniLock(myMutex);

2、unique_lock的第二个参数

2.1 std::adopt_lock:

std::adopt_lock:标记作用,表示这个互斥量已经被lock()(方便记忆:已经被lock()收养了,不需要再次lock() ),即不需要在构造函数中lock这个互斥量了。
前提必须提前lock,否则会出错
lock_guard中也可以用这个参数

2.2 std::try_to_lock:

  • 尝试用mutex的lock()去锁定这个mutex,但如果没有锁定成功,会立即返回,不会阻塞在那里
  • 使用try_to_lock的原因是防止其他的线程锁定mutex太长时间,导致本线程一直阻塞在lock 这个地方
    前提不能提前lock();
    owns_lock()方法判断是否拿到锁,如拿到返回true
    实例:
    假设
    线程1 执行下例代码时,先锁定互斥量myMutex1
    ,然后暂停了2s,才继续执行程序。线程1执行的代码如下
bool outMsgProc(int &num)
{unique_lock<mutex> muGuard(myMutex1);chrono::milliseconds time(2000);    //线程暂停2sthis_thread::sleep_for(time);if (!myList.empty()){num = myList.front();myList.pop_front();return true;}return false;
}

在此期间,如果线程2也尝试锁定myMutex1,就只能阻塞,直到线程1释放锁后,才能继续执行。线程2执行的代码如下:

void InMsg()
{for (int i = 0; i < 10000; i++){cout << "插入元素: " << i << endl;unique_lock<mutex> muGuard(myMutex1);myList.push_back(i);			}
}

显然,这样的程序效率不高。线程2花费了太多的时间等待。

我们考虑使用try_to_lock,线程尝试获取锁,如果没有锁定成功,它不会阻塞在那里,可以去执行其他代码。改进后的代码如下:

void InMsg()
{for (int i = 0; i < 10000; i++){cout << "插入元素: " << i << endl;unique_lock<mutex> muGuard(myMutex1, try_to_lock);if (muGuard.owns_lock())// 判断是否拿到锁{myList.push_back(i);}else{//没有拿到锁时,执行的代码}}
}

2.3 std::defer_lock:

  • 如果没有第二个参数就对mutex进行加锁,加上defer_lock是始化了一个没有加锁的mutex
  • 不给它加锁的目的是以后可以调用unique_lock的一些方法
  • 前提不能提前lock

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

3.1 lock():加锁。

unique_lock<mutex> muGuard(myMutex, defer_lock);
muGuard.lock();//手动加锁

不用自己unlock();

3.2 unlock():解锁。

unique_lock<mutex> muGuard(myMutex, defer_lock);
muGuard.lock();
//处理一些共享代码
muGuard.unlock();
//临时处理一些非共享代码
muGuard.lock();
//处理一些共享代码,处理完之后,自动解锁

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

try_to_lock是unique_lock的第二个参数,try_lock()是unique_lock()的成员变量。
如果拿不到锁,返回false,否则返回true(然后上锁)。

 unique_lock<mutex>muGuard(myMutex, defer_lock);//mutex1.lock();//自动解锁if (muGuard.try_lock() == true) {cout << "插入数据: " << num << endl;test_list.push_back(num);}else {cout << "in_list()执行,但没有拿到锁" << num << endl;}

3.4 release():

release():就是解除绑定,返回它所管理的mutex对象的指针,并释放所有权。

  1. unique_lock<mutex>muGuard(myMutex1);
    相当于把myMutex(mutex对象)和 muGuard绑定在了一起
  2. mutex* ptx =muGuard.release();
    也就是说 muGuard和mutex不在有联系,后续myMutex所有权由ptx接管,如果原来mutex对象处理加锁状态,就需要ptx在以后进行解锁了。
for (int num = 0; num < 10000; num++) {unique_lock<mutex> muGuard(myMutex);mutex* ptx = muGuard.release();//解除myMutex1(mutex对象)和 muGuard绑定//操作事务test_list.push_back(num);ptx->unlock();//myMutex1所有权由ptx接管,由ptx进行解锁
}

lock的代码段越少,执行越快,整个程序的运行效率越高。

  • 锁住的代码少,叫做粒度细,执行效率
  • 锁住的代码多,叫做粒度粗,执行效率
    -只锁定共享的数据

4.unique_lock所有权的传递

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

4.1 使用move转移

unique_lock<mutex> muGuard2(std::move(muGuard1));
之前muGuard1拥有myMutex的所有权,muGuard1可以把自己对myMutex的所有权转移,但是不能复制。现在muGuard2拥有myMutex的所有权。

4.2. 在函数中return一个临时变量,也可以实现转移

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/45853.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LVS 负载均衡集群

集群 集群&#xff08;Cluster&#xff09;是一组相互连接的计算机或服务器&#xff0c;它们通过网络一起工作以完成共同的任务或提供服务。集群的目标是通过将多台计算机协同工作&#xff0c;提高计算能力、可用性、性能和可伸缩性&#xff0c;适用于大量高并发的场景。 集群…

【HBZ分享】java中的BitSet 与 Redis中的BitMap 与 布隆过滤器

BitMap的存储原理 bitMap他会标识出某个整数是否存在&#xff0c;存在即为1&#xff0c;不存在对应位即为0bitMap是存储int类型的&#xff0c;int 4byte&#xff0c; 1byte 8bit&#xff0c;因此bitMap数组中的每个下标可以标识出32个数字是否存在bitMap相当于一个个小格子&…

马哈鱼数据血缘工具背后的项目: gsp_demo_java 项目简单介绍与使用

0.背景 马哈鱼数据血缘工具(https://www.sqlflow.cn/)是SQLflow工具的中文译名,实际就是sqlflow. 对于SQL flow来说,底层调用的是General SQL Parser(GSP https://sqlparser.com) 的库. 这个gsp有开源的java demo项目:https://github.com/sqlparser/gsp_demo_java 1.快速使用…

第6章:支持向量机

间隔与支持向量 w为法向量&#xff0c;决定的是超平面的方向。b是偏移项&#xff0c;决定了超平面与原点之间的距离。 为什么最大化间隔&#xff0c;得到的就是最优平面呢&#xff1f; 当超平面没有正确划分正负样本时&#xff0c;几何间隔为负数。几何间隔&#xff0c;各个…

网络编程基础(1)

目录 网络编程解决是跨主机的进程间通讯 1、网络 2、互联网 3、ip地址 &#xff08;1&#xff09;ipv4: &#xff08;2&#xff09;ipV6:1 &#xff08;3&#xff09;IP地址的组成&#xff1a; (4)Linux查看IP地址&#xff1a;ifconfig 4、mac地址 5、ping Ip地址 6…

【python最大公因数、最小公倍数】

文章目录 最大公约数/最小公倍数辗转相除法求最大公约数/公倍数—暴力穷举求最大公约数/公倍数—辗转相除 最大公约数/最小公倍数 最大公约数&#xff08;GCD&#xff09;&#xff1a; 最大公约数是指两个或多个整数中能够同时整除的最大的正整数。也就是说&#xff0c;如果 a …

VisualVM(All-in-One Java Troubleshooting Tool)多合-故障处理工具

VisualVM&#xff1a;多合-故障处理工具 VisualVM&#xff08;All-in-One Java Troubleshooting Tool&#xff09;是功能最强大的 运行监视 和 故障处理 程序之一&#xff0c;曾经在很长一段时间内是Oracle官方主力发展的虚拟机故障处理工具。Oracle曾在VisualVM的软件说明中写…

数据结构--最短路径 Floyd算法

数据结构–最短路径 Floyd算法 F l o y d 算法&#xff1a;求出每⼀对顶点之间的最短路径 \color{red}Floyd算法&#xff1a;求出每⼀对顶点之间的最短路径 Floyd算法&#xff1a;求出每⼀对顶点之间的最短路径 使⽤动态规划思想&#xff0c;将问题的求解分为多个阶段 对于n个顶…

JRE、JDK、JVM及JIT之间有什么不同?_java基础知识总结

当涉及Java编程和执行时&#xff0c;以下术语具有不同的含义&#xff1a; 1.JRE (Java Runtime Environment) JRE是Java运行时环境的缩写。它是一个包含用于在计算机上运行Java应用程序所需的组件集合。JRE包括了以下几个主要部分&#xff1a; Java虚拟机(JVM)&#xff1a;用…

【开源三方库】bignumber.js:一个大数数学库

OpenHarmony&#xff08;OpenAtom OpenHarmony简称“OpenHarmony”&#xff09;三方库&#xff0c;是经过验证可在OpenHarmony系统上可重复使用的软件组件&#xff0c;可帮助开发者快速开发OpenHarmony应用。如果是发布到开源社区&#xff0c;称为开源三方库&#xff0c;开发者…

QT学习笔记-Linux ARM环境下实现QT程序通过ODBC驱动访问SQLServer数据库

QT学习笔记-Linux ARM环境下实现QT程序通过ODBC驱动访问SQLServer数据库 0、背景1、基本环境2、搭建交叉编译环境3、在交叉编译服务器上交叉编译安装unixODBC3.1 下载unixODBC3.2 交叉编译unixODBC3.2.1 基本编译说明3.2.2 交叉编译说明3.2.3 ./configure -build,-host,-target…

设计模式8:代理模式-静态代理

我尝试在JDK、Android SDK和一些出名的库中&#xff0c;寻找静态代理的源码&#xff0c;没能找到。如果有读者发现&#xff0c;欢迎评论或者私信我。 本文目录 静态代理的实例1. 售票代理2. 明星代理 静态代理的实例 1. 售票代理 售票服务 public interface TicketService {…

不知道开黑语音哪个软件好?

黑盒语音官方网站&#xff1a;https://chat.top 免费支持AI降噪免费支持高品质立体声免费支持码率128Kbps,192Kbps免费支持上传100M文件免费支持动态房间头像和横幅支持更多自定义动态表情即将支持更多免费功能

IP 地址监控工具

地址监控实用程序是一套 IP 工具&#xff0c;包括 IP 地址监控工具、流氓检测工具和 MAC 地址解析器&#xff0c;用于日常监控和管理 DNS 名称、IP和 MAC 地址。地址监控工具用于 IP监控&#xff0c;用于管理 DNS 名称、网络的 IP 和 MAC 地址&#xff0c;并跟踪 IP 地址。 IP…

博冠光电8K事业部招聘研发工程师及产品经理

一、高级结构工程师 工作职责&#xff1a;1、负责公司产品的机械结构设计、模具开发和量产导入&#xff1b;2、负责机械结构方向的技术预研&#xff0c;包括技术专题研究&#xff0c;技术难题攻关&#xff1b; 3、负责结构组的技术管理工作&#xff0c;包括带新人&#xff0c;…

字符串拼接操作的面试题讲解

1、字符串拼接操作 常量与常量的拼接结果在常量池&#xff0c;原理是编译期优化。String s1"a""b""c";常量池中不会存在相同内容的常量。只要其中有一个是变量&#xff0c;结果就在 堆 中。变量拼接的原理是StringBuilder。如果拼接符号的前后出…

JavaScript中的this关键字的作用,以及它如何确定其值

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ this关键字的作用⭐ this的值取决于执行上下文⭐ 示例⭐ 总结⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅&#xff01;这…

MySQL数据库第十四课--------sql优化---------层层递进

作者前言 &#x1f382; ✨✨✨✨✨✨&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f382; ​&#x1f382; 作者介绍&#xff1a; &#x1f382;&#x1f382; &#x1f382; &#x1f389;&#x1f389;&#x1f389…

极光笔记 | 如何为您的业务开发和训练一个AI-BOT

生成式AI&#xff08;Generative AI&#xff09;是当今科技领域的前沿技术之一。随着数据量的不断增加和计算能力的不断提升&#xff0c;AI技术在企业和个人生活中的应用越来越广泛。AI-BOT&#xff08;以下简称BOT&#xff09;是生成式AI技术的其中一种重要的应用形式&#xf…

最小二乘拟合圆柱

目录 一、算法原理二、代码实现 本文由CSDN点云侠原创&#xff0c;原文链接。如果你不是在点云侠的博客中看到该文章&#xff0c;那么此处便是不要脸的爬虫。 一、算法原理 由圆柱面的几何特性可得&#xff0c;圆柱面上的点到其轴线的距离恒等于半径 r 0 r_0 r0​&#xff0c;…