C++多线程(七):unique_lock详解

2023-11-17

unique_lock取代lock_guard

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

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

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

的效果是一样的。

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);

执行过这句话之后(在这句话之前不能先使用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;
}

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进行加锁操作

对于没有加锁的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进行加锁操作

为什么要使用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())
{
	//上锁成功,进行数据处理
}

成员函数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();//手动解锁,如果不解锁会卡住导致程序崩溃

unique_lock所有权的传递(转移)

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

所有权概念

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

表示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

也可以通过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的移动构造函数
}

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

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

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++多线程(七):unique_lock详解 的相关文章

  • Web UI 中的 .Result 出现死锁

    我正在阅读以下主题http blog stephencleary com 2012 07 dont block on async code html http blog stephencleary com 2012 07 dont bloc
  • 如何向 UWP 项目添加 .NET dll 引用?

    我有几个适用于 NETv4 x 的 NET dll 项目 我将版本更改为 4 6 1 并重新构建 没有出现问题 当我尝试从 UWP 项目向它们添加引用时 出现错误 项目的目标是 NETCore 而文件引用的目标是 NET框架 这不是受支持的
  • 实体框架代码优先 - 在另一个文件中配置

    使用 Fluent API 将表到实体的映射分开的最佳方法是什么 以便它全部位于单独的类中 而不是内联在 OnModelCreating 方法中 我目前在做什么 public class FooContext DbContext prote
  • .NET 可移植类库中的 .ToShortDateString 发生了什么

    我想知道为什么没有 ToShortDateString在 NET 可移植类库中 我有 2 个项目 Silverlight 和常规 NET 类库 使用相同的代码 并且代码涉及调用 ToShortDateString on a DateTime
  • 使用 C# 使用应用程序密码登录 Office 365 SMTP

    在我们的 Office 365 公司帐户中实施两步身份验证之前 我的 C WPF 程序已成功进行身份验证并发送邮件 我使用了 SmtpClient 库 但现在我必须找到另一个解决方案 因为它不再起作用 我找不到任何使用 O365 应用程序密
  • 浮点提升:stroustrup vs 编译器 - 谁是对的?

    在 Stroustrup 的新书 C 编程语言 第四版 第 10 5 1 节中 他说 在执行算术运算之前 整数提升用于从较短的整数类型创建整数 类似地 浮点提升是用于从浮点数创建双精度数 我用以下代码确认了第一个声明 include
  • 身份未映射异常

    System Security Principal IdentityNotMappedException 无法转换部分或全部身份引用 该错误仅在应用程序注册后出现一次 当 SecurityIdentifier 无法映射时 例如 返回 Ide
  • 字节到二进制字符串 C# - 显示所有 8 位数字

    我想在文本框中显示一个字节 现在我正在使用 Convert ToString MyVeryOwnByte 2 但是 当字节开头有 0 时 这些 0 就会被删除 例子 MyVeryOwnByte 00001110 Texbox shows g
  • __FUNCTION__ 宏的 C# 版本

    有人对 C FUNCTION 宏的 C 版本有好的解决方案吗 编译器似乎不喜欢它 尝试使用这个代替 System Reflection MethodBase GetCurrentMethod Name C 没有 LINE or FUNCTI
  • 阅读 Stack Overflow RSS 源

    我正在尝试获取未回答问题的列表the feed https stackoverflow com feeds 但我在阅读时遇到困难 const string RECENT QUESTIONS https stackoverflow com f
  • 防止复制构造和返回值引用的分配

    如果我有一个函数返回对类实例的引用 但我无法控制其源 比如说list
  • CMake - 将预构建库链接到 C# 项目

    我正在使用 CMake 构建 C 库 该库依赖于已构建的库 dll 我似乎无法让图书馆链接到我的图书馆 我尝试过使用target link libraries mylib external lib 我也尝试过暴力破解 reference e
  • 在可观察项目生成时对其进行处理

    我有一个IObservable它会生成一次性物品 并且在其生命周期内可能会生成无限数量的物品 因此 我想在每次生成新项目时处理最后一个项目 因此Using http reactivex io documentation operators
  • 为什么 C 函数不能返回数组类型?

    我是 C 语言新手 想知道 为什么 C 函数不能返回数组类型 我知道数组名是数组第一个值的地址 而数组是 C 中的二等公民 您自己已经回答了这个问题 数组是二等公民 C 按值返回 数组不能按值传递 因此不能返回它们 至于为什么数组不能按值传
  • 通过 MSBuild 调用 cl.exe 时无限期挂起

    我正在尝试在我的 主要是 C 项目上运行 MSBuild 想象一下一个非常庞大的代码库 Visual Studio 2015 是有问题的工具集 Windows 7 SP1 和 VS 2015 更新 2 即使使用 m 1 从而迫使它仅使用一个
  • 改进C++逐行读取文件的能力?

    我正在解析大约 500GB 的日志文件 我的 C 版本需要 3 5 分钟 我的 Go 版本需要 1 2 分钟 我正在使用 C 的流来流式传输文件的每一行以进行解析 include
  • 在 unix 中编译 dhrystone 时出错

    我是使用基准测试和 makefile 的新手 我已经从下面的链接下载了 Dhrystone 基准测试 我正在尝试编译它 但我遇到了奇怪的错误 我尝试解决它 但没有成功 有人可以帮助我运行 dhrystone 基准测试吗 以下是我尝试编译的两
  • 多个同名内存数据库

    关系到这个答案 https stackoverflow com a 48446491 596758 我试图通过设置让多个上下文工作UseInMemoryDatabase以同名 下面的测试失败 第二个上下文为空 我还需要做什么才能在内存数据库
  • 在 C# 中读取/写入命令行程序

    我正在尝试与 C 的命令行程序进行对话 它是一个情绪分析器 它的工作原理如下 CMD gt java jar analyser jar gt Starting analyser 这是我想从我的 C 程序插入内容的地方 例如 I love y
  • 最后从同一类中的其他构造函数调用构造函数

    我在这里读到可以调用另一个构造函数从同一类中的另一个构造函数调用构造函数 https stackoverflow com questions 829870 calling constructor from other constructor

随机推荐

  • python3.7 连接sql server出现pymssql.OperationalError: (20009, b'DB-Lib error message 20009, severity 9:\...

    今天在使用python3 7中的pymssql 连接sqlserver的时候遇到的问题 pymssql OperationalError 20009 b DB Lib error message 20009 severity 9 nUnab
  • 区块链-公钥生成地址

    目录 https blog csdn net qq 40452317 article details 89646633 比特币 区块链 地址是一个由数字和字母组成的字符串 由公钥 一个同样由数字和字母组成的字符串 生成的比特币地址以数字 1
  • UE4/UE5 动画控制

    工程下载 https mbd pub o bread ZJ2cm5pu 蓝图控制sequence播放 倒播动画 设置开启鼠标指针 开启鼠标事件 在场景中进行过场动画制作 设置控制事件
  • 滚动页面触发相应位置动画 ---react

    需要实现的效果 滚动到内容区域触发 第一段内容移动效果 第二段内容淡入 第三段内容缩放 实现思路 滚动过的距离 当前窗口的高度 gt 元素到顶部窗口的距离 gt 则触发动画 整体代码 import React useRef useEffec
  • Rust 取代 C++ ?

    https www zhihu com question 27608498 作者 天象 链接 https www zhihu com question 27608498 answer 50130876 来源 知乎 著作权归作者所有 商业转载
  • CSS 文字特效运用目录

    主要是记录文字相关的特效实践案例和实现思路 章节名称 完成度 难度 文章地址 完整代码下载地址 创意填充文本悬停效果 完成 一般 文章链接 代码下载 发光文字跟随鼠标 完成 一般 文章链接 代码下载 酷炫的文字悬停效果 完成 一般 文章链接
  • checkbox中checked属性总结

    一 checked属性定义和用法 1 checked属性是一个布尔属性 2 checked属性规定在页面加载时应该被预先选定的
  • 数据库连接的5种方式

    数据库连接的5种方式 String url jdbc mysql localhost 3306 njustzjc1 Properties properties new Properties properties setProperty us
  • 基础理解之SESSION

    SESSION是服务器端的一种会话机制 当客户端的请求服务器创建一个SESSION时 服务器会先检测该请求里面是否包含一个惟一的sesionid 如果是 说明服务器已经为该用户创建过SESSION 只要按照该sesionid检索出该用户的s
  • 在钉钉上怎么手写_大庆市第十中学

    有关直播的那些事儿 2020 停课不停学 十中在行动 根据大庆市教育局关于网络教学工作的要求和指导意见 我校将于3月2日全面开展网络教学工作 虽然网络直播教学与线下日常教学主旨都是一样的 但由于形式的差异 对于很少体验过网络直播教学的老师来
  • 红米ac2100 刷openwrt以及刷回记录

    redmiac2100 刷机 参考 手动升级漏洞固件 https wwx lanzoux com i6iqxhqp98f 或者百度网盘链接 https pan baidu com s 1H355Ym9p TLrVOux2w2b7Q 提取码
  • Flutter开发之——Icon图标

    一 概述 Icon是支持material design的一系列图标 Icon类似于iconfont即字体图标 它是将图标做成字体文件 然后通过指定不同的字符显示不同图片 二 Icon说明 2 1 说明 在字体文件中 每一个字符都对应一个位码
  • Android内存管理

    Android内存泄露 全解析和处理办法 http www jianshu com p bf159a9c391a
  • 产品运行所需的信息检索失败。请重新安装xshell

    产品运行所需的信息检索失败 请重新安装xshell 很久没有应用Xshell进行远程服务器连接了 由于需要应用远程云计算资源 因此有需要使用这个软件 但是在今天的使用过程中出现了 问题 打开Xshell之后 找到可执行文件之后 点击运行 管
  • 【CQOI 2015】任务查询系统

    题目 传送门 题目描述 最近实验室正在为其管理的超级计算机编制一套任务管理系统 而你被安排完成其中的查询部分 超级计算机中的任务用三元组 Si Ei Pi 描述 Si Ei Pi 表示任务从第 Si 秒开始 在第 Ei 秒后结束 第 Si
  • 电脑开不了机启动不了

    故障现象 解决办法 1 先不要操作别的 首先想想开机之前做过什么操作 更新过什么 补丁 漏洞 软件 还是别的等等 2 重启操作系统 在开机的时候不停地按F8键 如果不停地按之后出现了一个黑底白字的菜单 可以最后一次配置试试 不行可以进入系统
  • 服务器CPU经常跑高是什么原因

    服务器在使用过程中 经常会遇见这样的情况 在长时间使用之后 系统运行会越来越慢 卡的情况 查询后台进程 CPU占用以超过90 那么高的CPU使用率 都是会由哪些因素导致的呢 1 散热故障 如机房散热不足 温度过热或者驱动故障 导致温度太高
  • html新闻滚动效果,js实现滚动新闻效果

    code js cn a display block font size 15px line height 18px text decoration none color 333 font family Arial font size 12
  • 机器学习-泛化能力笔记

    1 什么是泛化能力 在机器学习方法中 泛化能力通俗来讲就是指学习到的模型对未知数据的预测能力 在实际情况中 我们通常通过测试误差来评价学习方法的泛化能力 2 泛化误差的定义 大家马上应该发现 这个不是损失函数的期望吗 没错 泛化误差就是所学
  • C++多线程(七):unique_lock详解

    目录 unique lock取代lock guard unique lock的第二个参数 std adopt lock std try to lock std defer lock unique lock的成员函数 成员函数lock 成员函