【C++多线程编程:六种锁】
目录
普通互斥锁:
轻量级锁
独占锁:
std::lock_guard:
std::unique_lock:
共享锁:
超时的互斥锁
递归锁
普通互斥锁:
std::mutex确保任意时刻只有一个线程可以访问共享资源,在多线程中常用于保护共享资源。
互斥锁的实现示例:
#include <iostream>
#include <thread>
#include <mutex>std::mutex Mutex;
int shared_source = 1;void Shared_data()
{//获取锁Mutex.lock();shared_source++;std::cout << "shared_source : " << shared_source <<" by thread :"<<std::this_thread::get_id()<< std::endl;//锁释放Mutex.unlock();
}
int main()
{std::thread thread1(Shared_data);std::thread thread2(Shared_data);thread1.join();thread2.join();return 0;
}
在实际使用的过程中,如果容易忘记对锁进行释放,可以使用std::unique_lock和std::lock_guard安全的管理锁的释放。
轻量级锁
在C++中,轻量级锁通常指的是一些开销较小,性能较高的锁机制,C++并没有直接提供“轻量级锁”的概念,可以通过一个自旋锁来达到实现轻量级锁的目的。
适用场景:竞争不激烈,比如在大多数时间里中有一个线程需要访问临界区的情况。但如果竞争激烈会导致CUP资源的浪费(CPU自旋),降低性能。
自旋锁:一种简单的锁机制,当线程尝试获取锁时,如果锁已被其他线程占用,则当前线程会不断地循环等待,直到锁可用
自旋锁的示例:
#include <iostream>
#include <thread>
#include <atomic>std::atomic<bool>spinlock(false);void spin_lock()
{while (spinlock.exchange(true, std::memory_order_acquire)){//如果锁被占用则一直自旋,等待锁可用}
}void spin_unlock()
{spinlock.store(false, std::memory_order_release);//释放锁,并将锁的状态写入内存中
}
void critical_section()
{spin_lock();std::cout << "mutex acquire by thread : " << std::this_thread::get_id() << std::endl;
// std::this_thread::sleep_for(std::chrono::seconds(1));spin_unlock();//锁释放
}
int main()
{std::thread t1(critical_section);std::thread t2(critical_section);t1.join();t2.join();return 0;
}
独占锁:
std::unique_lock和std::lock_guard都是cpp标准库提供的管理互斥锁的类,他们都提供了自动锁和解锁的功能。但二者存在一些关键区别:
std::lock_guard:
- std::lock_guard并不是一种锁,而是一个作用域锁管理,一个能管理锁生命周期的工具,用于简化互斥锁的使用,确保在作用域结束后自动释放锁,避免死锁问题
- 自动加锁和解锁:在构造时自动加锁,在析构时自动解锁,不需要显示的调用加锁和解锁的方法
- 不支持条件变量配合使用:条件变量需要可以临时释放锁并重新获取锁,但是lock_guard并没有提供unlock().
- 使用场景:适用于不需要显示控制加锁和解锁的场景,或者不需要与条件变量配合使用的场景,适用于在某个作用域中同步访问共享资源的场景
lock_guard示例:
#include <iostream>
#include <thread>
#include <mutex>std::mutex mtx;
int shared_data = 0;void worker()
{std::lock_guard<std::mutex>lock(mtx);//自动加锁shared_data++;std::cout << "shared_data ++ by thread : " << std::this_thread::get_id() << std::endl;//自动解锁,无需显示调用unlock()
}
int main()
{std::thread t1(worker);std::thread t2(worker);t1.join();t2.join();return 0;
}
std::unique_lock:
- std::unique_lock本身不是一种锁,而是一个可选的互斥锁管理器,提供了对互斥锁的更加灵活的控制方式
- 显示加锁和解锁:提供了lock()和unlock()方法,可以显示的加锁和解锁,也可以在构造时自动加锁
- 可以与条件变量配合
- 自动管理锁的生命周期,避免了因忘记解锁而导致的死锁问题
- 使用场景:需要显示控制加锁和解锁时机,或者需要和条件变量配合使用的场景
unique_lock实例:
#include <iostream>
#include <thread>
#include <mutex>std::mutex mtx;
int shared_data = 0;
char str = 'a';//不显示调用加解锁,自动加锁和解锁
void worker()
{std::unique_lock<std::mutex>lock(mtx);//defer_lock =>延迟锁定操作,需要在特定的时机才锁定互斥锁shared_data += 1;std::cout << "shared_data ++ :" << shared_data << " ,by thread : " << std::this_thread::get_id() << std::endl;std::cout << "str: " << str++ << " ,by thread: " << std::this_thread::get_id() << std::endl;}
//显示调用加锁和解锁
void worker()
{std::unique_lock<std::mutex>lock(mtx,std::defer_lock);//defer_lock =>延迟锁定操作,需要在特定的时机才锁定互斥锁shared_data+=1;std::cout << "shared_data ++ :"<<shared_data<<" ,by thread : " << std::this_thread::get_id() << std::endl;lock.lock();//延迟锁定std::cout << "str: " << str++ <<" ,by thread: "<< std::this_thread::get_id() << std::endl;lock.unlock();//显示解锁
}int main()
{std::thread t1(worker);std::thread t2(worker);t1.join();t2.join();return 0;
}
独占锁与mutex相比,更加的安全,它可以避免忘记手动解锁,会在其作用域结束时自动的释放锁
共享锁:
在C++中,共享锁允许多个线程共享读取资源,但在写入资源时只允许一个线程写入数据,要求独占锁。当某个线程获取了独占锁时,其他线程无法获取任何形式地锁,而当多个线程获取共享锁时,他们可以同时读取共享资源
使用场景:适用于读多写少的场景下,能有效提高多线程程序的性能
示例:
#include <iostream>
#include <thread>
#include <shared_mutex>std::shared_mutex mtx;
int shared_data = 0;
void read_data()
{//获取共享锁std::shared_lock <std::shared_mutex> lock(mtx);std::cout << "Reading data : " << shared_data << std::endl;
}
void write_data()
{//获取独占锁std::unique_lock<std::shared_mutex>lock(mtx);shared_data = 24;std::cout << "Writing data : " << shared_data << std::endl;
}
int main()
{std::thread t1(read_data);std::thread t2(read_data);std::thread t3(write_data);t1.join();t2.join();t3.join();return 0;
}
超时的互斥锁
C++标准库提供了timed_mutex来实现该功能,支持超时机制,当线程尝试获取锁时,可以指定一个超时时间,如果在该时间内无法获取锁,线程将返回并继续执行其他任务。通过使用超时互斥锁,可以有效的避免线程在等待锁时无限地阻塞,提高程序地响应和稳定性
示例:
#include <iostream>
#include <thread>
#include <mutex>
#include <chrono>//超时锁
//C++标准库提供的互斥锁之一,支持在尝试获取锁时设置超时时间
std::timed_mutex mtx;void function_time()
{//在1s内获取锁//try_lock_for在指定时间内获取锁,成功返回true,失败则false//参数chrono是一个时间间隔类型的一个域if (mtx.try_lock_for(std::chrono::seconds(1))){std::cout << "Lock acquired " << std::endl;//模拟耗时操作//在当前线程休眠这2s内,其他线程无法获取该锁//所以当t2尝试获取锁时,t1持有锁并休眠2s,当锁释放后,t2锁获取超时std::this_thread::sleep_for(std::chrono::seconds(2));mtx.unlock();//释放锁}else{std::cout << "Fail to acquire lock within 1s" << std::endl;}
}
int main()
{//主线程创建的这俩线程几乎同时开始执行function_time函数std::thread t1(function_time);std::thread t2(function_time);t1.join();t2.join();return 0;
}
递归锁
递归锁:同一个线程多次获取同一把锁,而不会导致死锁。cpp中没有直接提供递归锁的实现,但是可以通过reecursive_mutex来实现递归锁的功能。
reecursive_mutex:一个可重入的互斥锁,允许同一个线程多次调用lock或try_lock来获取锁,不会导致死锁。
使用场景:需要在同一个线程中多次获取锁的场景
递归锁示例:
#include <iostream>
#include <thread>
#include <mutex>std::recursive_mutex mtx;void function(int n)//递归
{if (n > 0){mtx.lock();std::cout << "lock acquired by thread : " << std::this_thread::get_id() << " n ; " << n << std::endl;function(n - 1);mtx.unlock();}}int main()
{std::thread t1(function,3);std::thread t2(function,2);t1.join();t2.join();return 0;
}
相关文章:
![](https://www.ngui.cc/images/no-images.jpg)
【C++多线程编程:六种锁】
目录 普通互斥锁: 轻量级锁 独占锁: std::lock_guard: std::unique_lock: 共享锁: 超时的互斥锁 递归锁 普通互斥锁: std::mutex确保任意时刻只有一个线程可以访问共享资源,在多线程中常用于保…...
![](https://i-blog.csdnimg.cn/direct/3211d584df7c4e529006fcf3d61280db.png)
【Javascript Day5】for循环及典型案例
for 循环 // 语法: for( 开始 ; 结束 ; 步长 ){ 循环体 } // for( var i 循环初始值 ; i的循环范围 ; i的增加或减少规则 ){ 循环体 } // 死循环 // for(;;){ // console.log("for循环"); // } // 循环打…...
![](https://i-blog.csdnimg.cn/direct/cfc85783a19d48b4a3f40720d0e0fee7.png)
#渗透测试#网络安全#一文了解什么是shell反弹!!!
免责声明 本教程仅为合法的教学目的而准备,严禁用于任何形式的违法犯罪活动及其他商业行为,在使用本教程前,您应确保该行为符合当地的法律法规,继续阅读即表示您需自行承担所有操作的后果,如有异议,请立即停…...
![](https://i-blog.csdnimg.cn/direct/4445758e2ef14793bfce52953ccc1c0c.png)
《解锁图像的语言密码:Image Caption 开源神经网络项目全解析》
《解锁图像的语言密码:Image Caption 开源项目全解析》 一、开篇:AI 看图说话时代来临二、走进 Image Caption 开源世界三、核心技术拆解:AI 如何学会看图说话(一)深度学习双雄:CNN 与 RNN(二&a…...
![](https://i-blog.csdnimg.cn/direct/743ffbae896545d3b4b7a82e78842e51.jpeg)
抢占欧洲电商高地,TikTok 运营专线成 “秘密武器”
在当今数字化浪潮席卷全球的时代,社交媒体平台已成为商业拓展的关键阵地,TikTok 更是其中的闪耀新星。近日,一则重磅消息引发行业关注:TikTok 正计划于 2025 年初进军荷兰电商市场。这一战略布局,不仅彰显了 TikTok 对…...
![](https://www.ngui.cc/images/no-images.jpg)
人工智能-数据分析及特征提取思路
1、概况 基于学生行为数据预测是否涉黄、涉黑等。 2.数据分析 数据分析的意义包括得到数据得直觉、发掘潜在的结构、提取重要的变量、删除异常值、检验潜在的假设和建立初步的模型。 2.1数据质量分析 2.1.1数据值分析 查看数据类型: 首先明确各字段的数据类型…...
![](https://i-blog.csdnimg.cn/direct/483e7a8a5e0d4bc98828a99d29daa4fa.png)
2024 China Collegiate Programming Contest (CCPC) Zhengzhou Onsite 基础题题解
今天先发布基础题的题解,明天再发布铜牌题和银牌题的题解 L. Z-order Curve 思路:这题目说了,上面那一行,只有在偶数位才有可能存在1,那么一定存在这样的数,0 ,1,100, 10000,那么反之,我们的数…...
![](https://www.ngui.cc/images/no-images.jpg)
halcon3d 如何计算平面法向量!确实很简单
这个问题其实一直困扰了我很长时间,之前是怎么算的呢 对于一个平面,我会先求它的fit_primitives_object_model_3d去将它拟合,接下来用surface_normals_object_model_3d 算子生成它的法线,后用get_object_model_3d_params (ObjectModel3DNormals, ‘point_normal_x’, GenP…...
![](https://i-blog.csdnimg.cn/direct/f169fd62efa8404ca92f811d19a9b73d.png)
浅尝Appium自动化框架
浅尝Appium自动化框架 Appium自动化框架介绍Appium原理Appium使用安装平台驱动实战 坑 Appium自动化框架介绍 Appium 是一个开源的自动化测试框架,最初设计用于移动应用的测试,但现在它也扩展了对桌面端应用的支持。Appium 使得自动化测试变得更加简单&…...
![](https://www.ngui.cc/images/no-images.jpg)
网络安全测评技术与标准
网络安全测评概况 网络安全测评是网络信息系统和IT技术产品的安全质量保障。本节主要阐述网络安全测评的概念,给出网络安全测评的发展状况。 18.1.1 网络安全测评概念 网络安全测评是指参照一定的标准规范要求,通过一系列的技术和管理方法,获…...
![](https://i-blog.csdnimg.cn/direct/19a19b1d392944be90df72e4fa6b7b3d.png)
【经典神经网络架构解析篇】【1】LeNet网络详解:模型结构解析、优点、实现代码
《------往期经典推荐------》 一、AI应用软件开发实战专栏【链接】 项目名称项目名称1.【人脸识别与管理系统开发】2.【车牌识别与自动收费管理系统开发】3.【手势识别系统开发】4.【人脸面部活体检测系统开发】5.【图片风格快速迁移软件开发】6.【人脸表表情识别系统】7.【…...
![](https://www.ngui.cc/images/no-images.jpg)
KGA:AGeneral Machine Unlearning Framework Based on Knowledge Gap Alignment
文章目录 摘要1 引言2 相关工作3 符号与定义4 我们的 KGA 框架4.1 KGA框架知识差距对齐目标 4.2 KGA在自然语言处理任务中的应用文本分类机器翻译响应生成 5 实验设置数据集评估指标参数设置比较方法 6 实验结果6.1 主要比较结果6.2 KGA 的优越性分析降低语言模型概率比较 6.3 …...
![](https://i-blog.csdnimg.cn/direct/7a434009e68840d9aafcf4895babc182.png)
GelSight Mini视触觉传感器凝胶触头升级:增加40%耐用性,拓展机器人与触觉AI 应用边界
马萨诸塞州沃尔瑟姆-2025年1月6日-触觉智能技术领军企业Gelsight宣布,旗下Gelsight Mini视触觉传感器迎来凝胶触头的更新。经内部测试,新Gel凝胶触头耐用性提升40%,外观与触感与原凝胶触头保持一致。此次升级有效满足了客户在机器人应用中对设…...
![](https://www.ngui.cc/images/no-images.jpg)
springboot整合admin
1. 添加依赖 首先,在你的admin服务端pom.xml文件中添加Spring Boot Admin的依赖: <dependency><groupId>de.codecentric</groupId><artifactId>spring-boot-admin-starter-server</artifactId><version>2.5.4<…...
![](https://i-blog.csdnimg.cn/direct/8cb3acf15aea4b199fb34ff7f2b173d4.png#pic_center)
OS--常见的网络模型(包含IO多路复用的原理)
网络模型 IO模型主要就是用户空间和内核空间数据交换的形式。 IO模型 阻塞 I/O 模型(Blocking I/O) 应用程序发起 I/O 请求后,会被阻塞,直到 I/O 操作完成。 非阻塞 I/O 模型(Non-blocking I/O) 应用程序…...
![](https://www.ngui.cc/images/no-images.jpg)
LCE(Local Cascade Ensemble)预测模型和LSTM(Long Short-Term Memory)模型在效果和特点上存在显著差异
LCE(Local Cascade Ensemble)预测模型和LSTM(Long Short-Term Memory)模型在效果和特点上存在显著差异。以下是对两者的比较: 一、效果比较 LCE模型: 优势:LCE结合了随机森林和XGBoost的优势&a…...
![](https://www.ngui.cc/images/no-images.jpg)
【mysql】约束的基本使用
文章目录 1. PRIMARY KEY 约束1.1 作用1.2 关键字1.3 特点1.4 添加主键约束1.5 关于复合主键1.6 删除主键约束 2. 自增列:AUTO_INCREMENT2.1 作用2.2 关键字2.3 特点和要求2.4 如何指定自增约束2.5 如何删除自增约束2.6 MySQL 8.0新特性—自增变量的持久化 3. FOREI…...
![](https://i-blog.csdnimg.cn/direct/00badb00d6bb4db59078f9baa534379c.png)
EasyExcel(二)导出Excel表自动换行和样式设置
EasyExcel(一)导出Excel表列宽自适应 背景 在上一篇文章中解决导出列宽自适应,然后也解决了导出列宽不可超过255的问题。但是实际应用场景中仍然会有导出数据的长度超过列宽255。这时导出效果就会出现如下现象: 多出列宽宽度的内容会浮出来,影响后边列数据的显示。 解决…...
![](https://i-blog.csdnimg.cn/direct/20c62c66f2de4481a6527ba4cf6230c1.png)
农产品直播带货方案拆解
作为一名经验丰富的营销策划人道叔,今天我来拆解一下咱们4A营销广告圈的这份《直播天府川农好物带货方案》,让你能学到很多实用的策略和技巧,直接应用到你的策划工作中去。 首先,咱们看看背景分析。 助农直播现在可是个大热门&a…...
![](https://www.ngui.cc/images/no-images.jpg)
“**H5**” 和 “**响应式**” 是前端开发中常见的术语,但它们的概念和使用场景有所不同
“H5” 和 “响应式” 是前端开发中常见的术语,但它们的概念和使用场景有所不同。以下是它们的区别以及为什么为移动端开发的页面通常被称为 “H5” 的解释: 1. 为什么为移动端开发的叫 “H5”? “H5” 是 HTML5 的简称,HTML5 是…...
![](https://i-blog.csdnimg.cn/direct/fbab29ed926b495c859e6a566605fc0e.png)
基于EasyExcel实现通用版一对一、一对多、多层嵌套结构数据导出并支持自动合并单元格
接口功能 通用 支持一对一数据结构导出 支持一对多数据结构导出 支持多层嵌套数据结构导出 支持单元格自动合并 原文来自:https://blog.csdn.net/qq_40980205/article/details/136564176 新增及修复 基于我自己的使用场景,新增并能修复一下功能&#x…...
![](https://www.ngui.cc/images/no-images.jpg)
Java堆内存分析
(一)、线上查看堆内存统计 # 命令用于打印堆内存中每个类的实例数量及其占用的内存,并且只包括活动对象(即存活的对象) jmap -histo:live <pid># 输出到文件方便查看 jmap -histo:live 12345 > aaa.txt(二)、下载dump文件࿰…...
![](https://i-blog.csdnimg.cn/direct/353021eda5514ce7ab78fc0c07de8d07.png)
maven高级(day15)
Maven 是一款构建和管理 Java 项目的工具 分模块设计与开发 所谓分模块设计,顾名思义指的就是我们在设计一个 Java 项目的时候,将一个 Java 项目拆分成多 个模块进行开发。 分模块设计我们在进行项目设计阶段,就可以将一个大的项目拆分成若干…...
![](https://www.ngui.cc/images/no-images.jpg)
计算机组成原理(九):乘法器
乘法器原理 乘法器的工作原理可以用二进制乘法来说明。二进制乘法和十进制乘法类似,通过部分积的累加得到结果。 部分积的生成 在二进制乘法中,每一位的乘积是两个二进制数位的 与运算(0 0 0,1 0 0,0 1 0&…...
![](https://www.ngui.cc/images/no-images.jpg)
python【输入和输出】
Python 有三种输出值的方式: 表达式语句print() 函数使用文件对象的 write() 方法,标准输出文件可以用 sys.stdout 引用。 ① 将输出的值转成字符串,可以使用 repr() 或 str() 函数来实现: str(): 函数返回一个用户易…...
![](https://www.ngui.cc/images/no-images.jpg)
2024年华为OD机试真题-判断一组不等式是否满足约束并输出最大差-Python-OD统一考试(E卷)
最新华为OD机试考点合集:华为OD机试2024年真题题库(E卷+D卷+C卷)_华为od机试题库-CSDN博客 每一题都含有详细的解题思路和代码注释,精编c++、JAVA、Python三种语言解法。帮助每一位考生轻松、高效刷题。订阅后永久可看,发现新题及时跟新。 题目描述: 给定一组不等式…...
![](https://i-blog.csdnimg.cn/direct/529690eec5024e9f87107a1bd15224ff.png)
【json】
JSON JSON是一种轻量级的,按照指定的格式去组织和封装数据的数据交互格式。 本质上是一个带有特定格式的字符串(py打印json时认定为str类型) 在各个编程语言中流通的数据格式,负责不同编程语言中的数据传递和交互,类似于计算机普通话 python与json关系及相互转换…...
![](https://i-blog.csdnimg.cn/direct/64dbab8250d54fd590d40dddafadb4f3.png)
基于单片机的无线智能窗帘控制器的设计
摘 要 : 本文以单片机为控制核心 , 基于 PT2262/ 2272 无线收发模块 , 实现了窗帘的无线远程智能控制 . 该控制器通过高频无线收发模块实现了遥控窗帘的开合控制; 根据外部光线强弱实现自动开关窗帘 ; 根据设定时间自动完成开关过程; 通过语音播报当前环境温湿度信息以…...
![](https://i-blog.csdnimg.cn/direct/5c20c0087e044f158852084917103308.png#pic_center)
磁盘满造成业务异常问题排查
最近遇到一个因为磁盘满导致的问题,分享一下,希望能够帮助到以后遇到同样问题的朋友。 早上突然收到业务老师反馈说:上传文件不能正常上传了。 想想之前都好好的,最近又没有更新,为什么突然不能使用了呢?…...
![](https://www.ngui.cc/images/no-images.jpg)
C++例程:使用I/O模拟IIC接口(6)
完整的STM32F405代码工程I2C驱动源代码跟踪 一)myiic.c #include "myiic.h" #include "delay.h" #include "stm32f4xx_rcc.h" //初始化IIC void IIC_Init(void) { GPIO_InitTypeDef GPIO_InitStructure;RCC_AHB1PeriphCl…...
![](/images/no-images.jpg)
前端开发框架有哪些/苏州网站seo服务
dim current_dir as string Dim v_File New StreamReader(current_dir)Dim all_info As Stringall_info v_File.ReadToEnd()v_File.Close()v_File Nothing转载于:https://www.cnblogs.com/goodspeed-fish/archive/2013/05/21/3091728.html...
![](https://img-blog.csdnimg.cn/img_convert/76609db2875bda61d6ebf0fb66fe504a.png)
弥勒市建设局网站/怎么做好seo推广
你理想中的工作台是什么样的?现在很多小伙伴喜欢宅家办工,所以,在家里搞个像样的工作台就非常重要了!那么,家里究竟要一个怎么样的工作台,才可以宅着就能舒舒服服把砖搬了呢?小编为大家整理了15…...
![](/images/no-images.jpg)
用dw做网站首页步骤/百度的网址怎么写
这个网站没有反扒,使用的是Python 自带urllib ,解析库数xpath,生成器,数据保存到mongodb。代码 from urllib import request from pymongo import MongoClientfrom lxml import etreeclinet MongoClient(hostlocalhost, port27017) class R…...
![](https://img-blog.csdnimg.cn/img_convert/f8afc8376b51fa08114237a460944aeb.png)
怎么做加盟网站/国外媒体报道
原文转自https://blog.csdn.net/weixin_40427089/article/details/86624475欢迎关注我的CSDN博客~第二章并行计算,本质上来说,就是为了提升工作效率。使得一些工作可以更快地完成。那么如何衡量完成工作的快慢,自然是核函数花费时间的多少。这…...
![](https://img-blog.csdnimg.cn/2021040210133836.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0N5YmVyVmVpbg==,size_16,color_FFFFFF,t_70#pic_center)
黄石做企业网站/成人就业技术培训机构
本文转载自News BTC对CROSS的特别报道。以下为翻译的原文: 拍卖是财产权利转让的最古老方式之一。自从人类有了剩余价值的流动性需求,就有了拍卖这种方式。说到捡漏收藏界尽知的当属“明成化斗彩鸡缸杯”了。它的传承过程,似乎就是一部“拣大…...
![](https://img-blog.csdnimg.cn/20210306095514198.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1Ryb3V2YWlsbGVfYQ==,size_16,color_FFFFFF,t_70)
如何做网站淘宝客/百度数据指数
3D打印机加工一般可以打印什么东西? 3D打印(3DP)即快速成型技术的一种,又称增材制造,它是一种以数字模型文件为基础,运用粉末状金属或塑料等可粘合材料,通过逐层打印的方式来构造物体的技术。 …...