当前位置: 首页 > news >正文

【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;
}

相关文章:

【C++多线程编程:六种锁】

目录 普通互斥锁&#xff1a; 轻量级锁 独占锁&#xff1a; std::lock_guard&#xff1a; std::unique_lock: 共享锁&#xff1a; 超时的互斥锁 递归锁 普通互斥锁&#xff1a; std::mutex确保任意时刻只有一个线程可以访问共享资源&#xff0c;在多线程中常用于保…...

【Javascript Day5】for循环及典型案例

for 循环 // 语法&#xff1a; for( 开始 ; 结束 ; 步长 ){ 循环体 } // for( var i 循环初始值 ; i的循环范围 ; i的增加或减少规则 ){ 循环体 } // 死循环 // for(;;){ // console.log("for循环"); // } // 循环打…...

#渗透测试#网络安全#一文了解什么是shell反弹!!!

免责声明 本教程仅为合法的教学目的而准备&#xff0c;严禁用于任何形式的违法犯罪活动及其他商业行为&#xff0c;在使用本教程前&#xff0c;您应确保该行为符合当地的法律法规&#xff0c;继续阅读即表示您需自行承担所有操作的后果&#xff0c;如有异议&#xff0c;请立即停…...

《解锁图像的语言密码:Image Caption 开源神经网络项目全解析》

《解锁图像的语言密码&#xff1a;Image Caption 开源项目全解析》 一、开篇&#xff1a;AI 看图说话时代来临二、走进 Image Caption 开源世界三、核心技术拆解&#xff1a;AI 如何学会看图说话&#xff08;一&#xff09;深度学习双雄&#xff1a;CNN 与 RNN&#xff08;二&a…...

抢占欧洲电商高地,TikTok 运营专线成 “秘密武器”

在当今数字化浪潮席卷全球的时代&#xff0c;社交媒体平台已成为商业拓展的关键阵地&#xff0c;TikTok 更是其中的闪耀新星。近日&#xff0c;一则重磅消息引发行业关注&#xff1a;TikTok 正计划于 2025 年初进军荷兰电商市场。这一战略布局&#xff0c;不仅彰显了 TikTok 对…...

人工智能-数据分析及特征提取思路

1、概况 基于学生行为数据预测是否涉黄、涉黑等。 2.数据分析 数据分析的意义包括得到数据得直觉、发掘潜在的结构、提取重要的变量、删除异常值、检验潜在的假设和建立初步的模型。 2.1数据质量分析 2.1.1数据值分析 查看数据类型&#xff1a; 首先明确各字段的数据类型…...

2024 China Collegiate Programming Contest (CCPC) Zhengzhou Onsite 基础题题解

今天先发布基础题的题解&#xff0c;明天再发布铜牌题和银牌题的题解 L. Z-order Curve 思路&#xff1a;这题目说了&#xff0c;上面那一行&#xff0c;只有在偶数位才有可能存在1&#xff0c;那么一定存在这样的数&#xff0c;0 ,1,100, 10000,那么反之&#xff0c;我们的数…...

halcon3d 如何计算平面法向量!确实很简单

这个问题其实一直困扰了我很长时间,之前是怎么算的呢 对于一个平面,我会先求它的fit_primitives_object_model_3d去将它拟合,接下来用surface_normals_object_model_3d 算子生成它的法线,后用get_object_model_3d_params (ObjectModel3DNormals, ‘point_normal_x’, GenP…...

浅尝Appium自动化框架

浅尝Appium自动化框架 Appium自动化框架介绍Appium原理Appium使用安装平台驱动实战 坑 Appium自动化框架介绍 Appium 是一个开源的自动化测试框架&#xff0c;最初设计用于移动应用的测试&#xff0c;但现在它也扩展了对桌面端应用的支持。Appium 使得自动化测试变得更加简单&…...

网络安全测评技术与标准

网络安全测评概况 网络安全测评是网络信息系统和IT技术产品的安全质量保障。本节主要阐述网络安全测评的概念&#xff0c;给出网络安全测评的发展状况。 18.1.1 网络安全测评概念 网络安全测评是指参照一定的标准规范要求&#xff0c;通过一系列的技术和管理方法&#xff0c;获…...

【经典神经网络架构解析篇】【1】LeNet网络详解:模型结构解析、优点、实现代码

《------往期经典推荐------》 一、AI应用软件开发实战专栏【链接】 项目名称项目名称1.【人脸识别与管理系统开发】2.【车牌识别与自动收费管理系统开发】3.【手势识别系统开发】4.【人脸面部活体检测系统开发】5.【图片风格快速迁移软件开发】6.【人脸表表情识别系统】7.【…...

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 …...

GelSight Mini视触觉传感器凝胶触头升级:增加40%耐用性,拓展机器人与触觉AI 应用边界

马萨诸塞州沃尔瑟姆-2025年1月6日-触觉智能技术领军企业Gelsight宣布&#xff0c;旗下Gelsight Mini视触觉传感器迎来凝胶触头的更新。经内部测试&#xff0c;新Gel凝胶触头耐用性提升40%&#xff0c;外观与触感与原凝胶触头保持一致。此次升级有效满足了客户在机器人应用中对设…...

springboot整合admin

1. 添加依赖 首先&#xff0c;在你的admin服务端pom.xml文件中添加Spring Boot Admin的依赖&#xff1a; <dependency><groupId>de.codecentric</groupId><artifactId>spring-boot-admin-starter-server</artifactId><version>2.5.4<…...

OS--常见的网络模型(包含IO多路复用的原理)

网络模型 IO模型主要就是用户空间和内核空间数据交换的形式。 IO模型 阻塞 I/O 模型&#xff08;Blocking I/O&#xff09; 应用程序发起 I/O 请求后&#xff0c;会被阻塞&#xff0c;直到 I/O 操作完成。 非阻塞 I/O 模型&#xff08;Non-blocking I/O&#xff09; 应用程序…...

LCE(Local Cascade Ensemble)预测模型和LSTM(Long Short-Term Memory)模型在效果和特点上存在显著差异

LCE&#xff08;Local Cascade Ensemble&#xff09;预测模型和LSTM&#xff08;Long Short-Term Memory&#xff09;模型在效果和特点上存在显著差异。以下是对两者的比较&#xff1a; 一、效果比较 LCE模型&#xff1a; 优势&#xff1a;LCE结合了随机森林和XGBoost的优势&a…...

【mysql】约束的基本使用

文章目录 1. PRIMARY KEY 约束1.1 作用1.2 关键字1.3 特点1.4 添加主键约束1.5 关于复合主键1.6 删除主键约束 2. 自增列&#xff1a;AUTO_INCREMENT2.1 作用2.2 关键字2.3 特点和要求2.4 如何指定自增约束2.5 如何删除自增约束2.6 MySQL 8.0新特性—自增变量的持久化 3. FOREI…...

EasyExcel(二)导出Excel表自动换行和样式设置

EasyExcel(一)导出Excel表列宽自适应 背景 在上一篇文章中解决导出列宽自适应,然后也解决了导出列宽不可超过255的问题。但是实际应用场景中仍然会有导出数据的长度超过列宽255。这时导出效果就会出现如下现象: 多出列宽宽度的内容会浮出来,影响后边列数据的显示。 解决…...

农产品直播带货方案拆解

作为一名经验丰富的营销策划人道叔&#xff0c;今天我来拆解一下咱们4A营销广告圈的这份《直播天府川农好物带货方案》&#xff0c;让你能学到很多实用的策略和技巧&#xff0c;直接应用到你的策划工作中去。 首先&#xff0c;咱们看看背景分析。 助农直播现在可是个大热门&a…...

“**H5**” 和 “**响应式**” 是前端开发中常见的术语,但它们的概念和使用场景有所不同

“H5” 和 “响应式” 是前端开发中常见的术语&#xff0c;但它们的概念和使用场景有所不同。以下是它们的区别以及为什么为移动端开发的页面通常被称为 “H5” 的解释&#xff1a; 1. 为什么为移动端开发的叫 “H5”&#xff1f; “H5” 是 HTML5 的简称&#xff0c;HTML5 是…...

③ AI副业第一步:如何找到适合自己的AI赚钱赛道

③ AI副业第一步&#xff1a;如何找到适合自己的AI赚钱赛道选对赛道&#xff0c;努力才有意义。选错赛道&#xff0c;越努力离钱越远。前言&#xff1a;为什么大多数人AI副业做不起来&#xff1f; 我观察了100想做AI副业的人&#xff0c;失败的原因高度一致&#xff1a; 失败路…...

30岁裸辞后,我用两个月拿下AI应用认证,现在OFFER选择困难症犯了

30岁裸辞那天&#xff0c;我最怕的不是没收入&#xff0c;而是突然发现&#xff1a;过去积累的经验&#xff0c;正在被AI重新定价。以前会写方案、做表格、跟项目&#xff0c;算是职场硬通货&#xff1b;到了2026年&#xff0c;招聘JD里开始频繁出现AI工具应用、智能工作流、Pr…...

DeepSeek-R1补全能力封测倒计时(仅剩72小时开放API灰度权限):这份内部测试SOP已被3家头部科技公司紧急采购

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;DeepSeek-R1代码补全能力封测全景概览 DeepSeek-R1 是深度求索&#xff08;DeepSeek&#xff09;推出的高性能开源推理模型&#xff0c;在代码补全场景中展现出显著的上下文理解力与多语言泛化能力。本…...

Linux服务器被挖矿木马劫持的五步应急处置指南

1. 这不是“中病毒”&#xff0c;是服务器被劫持成了矿机——先别慌&#xff0c;但必须立刻断网“服务器被黑客攻击&#xff0c;用来挖矿&#xff01;”——这句话在运维圈里一出&#xff0c;比收到OOM告警还让人头皮发紧。它不像网页被挂马、数据库被拖库那样有明显业务影响&a…...

别被忽悠了!2026亲测靠谱的AI论文网站|避坑精选版

2026 年学术写作工具已高度分化&#xff0c;千笔AI与ThouPen为全流程首选&#xff0c;豆包、DeepSeek 为专项强手&#xff1b;避坑关键&#xff1a;拒绝假文献、严控 AIGC 率、优先国内适配、免费试用先行。 一、TOP3 全流程首选&#xff08;亲测不踩雷&#xff09; 1. 千笔AI&…...

独立开发者利用taotoken模型广场为不同任务选择性价比最优模型

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 独立开发者利用taotoken模型广场为不同任务选择性价比最优模型 对于独立开发者而言&#xff0c;在有限的预算内高效完成多样化的开…...

3分钟终极指南:用ncmdump轻松解密网易云音乐NCM格式文件

3分钟终极指南&#xff1a;用ncmdump轻松解密网易云音乐NCM格式文件 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗&#xff1f;ncmdump正是解决这个问题的神器&…...

为开源项目OpenClaw配置Taotoken作为其大模型服务后端

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 为开源项目OpenClaw配置Taotoken作为其大模型服务后端 OpenClaw 是一个功能强大的开源工具&#xff0c;它允许开发者便捷地调用各类…...

10.刷机变砖、IMEI 丢失、基带未知、触控失灵?一站式终极修复方案

摘要 本文面向具备基础计算机操作能力的维修从业者与高级用户,系统讲解当前主流品牌手机(华为、小米、OPPO、vivo、一加、苹果)的刷机与维修核心流程。内容涵盖底层引导架构差异、Fastboot/Recovery/DFU模式操作规范、分区表保护策略、驱动兼容性处理以及常见硬件故障的软件…...

终极指南:如何用Hindsight为聊天机器人添加长期记忆功能

终极指南&#xff1a;如何用Hindsight为聊天机器人添加长期记忆功能 【免费下载链接】hindsight Hindsight: Agent Memory That Learns 项目地址: https://gitcode.com/GitHub_Trending/hindsight2/hindsight Hindsight是一个革命性的AI代理记忆系统&#xff0c;专门为聊…...