C++17中的std::scoped_lock:简化多锁管理的利器
文章目录
- 1. 为什么需要std::scoped_lock
- 1.1 死锁问题
- 1.2 异常安全性
- 1.3 锁的管理复杂性
- 2. std::scoped_lock的使用方法
- 2.1 基本语法
- 2.2 支持多种互斥锁类型
- 2.3 自动处理异常
- 3. std::scoped_lock的优势
- 3.1 避免死锁
- 3.2 简化代码
- 3.3 提供异常安全保证
- 4. 实际应用场景
- 4.1 数据库连接池
- 4.2 线程安全的资源管理
- 4.3 复杂的多线程任务调度
- 5. 总结
在多线程编程中,锁是同步线程操作、保护共享资源的关键机制。然而,当需要同时管理多个锁时,代码的复杂度会急剧上升,尤其是涉及到锁的顺序和异常安全性时。C++17引入了std::scoped_lock,它极大地简化了多锁管理的复杂性,同时提供了异常安全的保证。本文将详细介绍std::scoped_lock的使用方法、优势以及它在实际开发中的应用场景。
1. 为什么需要std::scoped_lock
在多线程环境中,当多个线程需要访问共享资源时,通常会使用锁(如std::mutex)来防止数据竞争。然而,当需要同时操作多个互斥锁时,可能会遇到以下问题:
1.1 死锁问题
如果多个线程以不同的顺序获取多个锁,很容易导致死锁。例如,线程A先获取锁A再获取锁B,而线程B先获取锁B再获取锁A,这就会导致两个线程互相等待对方释放锁,从而陷入死锁。
1.2 异常安全性
在多锁场景中,如果在获取锁的过程中发生异常,可能会导致部分锁未正确释放,从而引发资源泄漏或其他未定义行为。
1.3 锁的管理复杂性
手动管理多个锁的获取和释放不仅容易出错,还会使代码变得冗长且难以维护。
std::scoped_lock正是为了解决这些问题而设计的。它提供了一种自动管理多个锁的机制,确保锁的获取和释放顺序正确,并且在异常情况下也能安全地释放所有锁。
2. std::scoped_lock的使用方法
std::scoped_lock是C++17标准库中新增的一个工具,它位于头文件中。它的主要作用是自动管理多个互斥锁的生命周期,确保这些锁在作用域结束时被正确释放。
2.1 基本语法
std::scoped_lock的构造函数接受一个或多个互斥锁对象作为参数,并在构造时自动锁定这些锁。当std::scoped_lock对象超出作用域时,它会自动释放所有锁。基本语法如下:
#include <mutex>
#include <thread>
#include <iostream>std::mutex mtx1;
std::mutex mtx2;void shared_resource_access() {std::scoped_lock lock(mtx1, mtx2); // 自动锁定mtx1和mtx2// 在这里安全地访问共享资源std::cout << "Accessing shared resources" << std::endl;
}int main() {std::thread t1(shared_resource_access);std::thread t2(shared_resource_access);t1.join();t2.join();return 0;
}
在上面的代码中,std::scoped_lock负责锁定mtx1和mtx2。当shared_resource_access函数执行完毕时,std::scoped_lock对象超出作用域,自动释放这两个锁。这种方式不仅简化了代码,还避免了死锁和异常安全问题。
2.2 支持多种互斥锁类型
std::scoped_lock不仅可以管理std::mutex类型的锁,还支持其他标准库提供的互斥锁类型,如std::recursive_mutex、std::timed_mutex等。例如:
std::recursive_mutex rmtx1;
std::timed_mutex tmtx2;void complex_resource_access() {std::scoped_lock lock(rmtx1, tmtx2);// 安全地访问需要递归锁和定时锁保护的资源std::cout << "Accessing complex shared resources" << std::endl;
}
2.3 自动处理异常
std::scoped_lock的一个重要特性是它能够自动处理异常。如果在锁的作用域内发生异常,std::scoped_lock会确保所有锁在异常传播之前被正确释放。这使得代码更加健壮,减少了因异常导致的资源泄漏风险。
3. std::scoped_lock的优势
3.1 避免死锁
std::scoped_lock通过内部机制确保以固定的顺序获取多个锁,从而避免了死锁的发生。它会按照某种固定的顺序(通常是锁的地址顺序)来锁定互斥锁,这样即使多个线程同时使用std::scoped_lock管理相同的锁,也不会出现死锁。
3.2 简化代码
使用std::scoped_lock可以显著减少锁管理相关的代码量。开发者无需手动锁定和解锁多个锁,只需将锁对象传递给std::scoped_lock即可。这不仅使代码更加简洁,也减少了出错的可能性。
3.3 提供异常安全保证
在多锁场景中,手动管理锁的释放很容易因为异常而变得复杂。std::scoped_lock通过RAII机制(资源获取即初始化)确保在异常情况下也能安全地释放所有锁,从而提供强异常安全保证。
4. 实际应用场景
4.1 数据库连接池
在多线程环境中,数据库连接池需要同时保护连接池的访问和连接的分配。std::scoped_lock可以用来同时锁定连接池的互斥锁和连接的互斥锁,确保操作的线程安全性。
4.2 线程安全的资源管理
当多个线程需要访问和修改共享资源时,std::scoped_lock可以用来同时锁定多个相关的互斥锁,从而确保资源的线程安全性。
4.3 复杂的多线程任务调度
在任务调度器中,可能需要同时锁定多个任务队列的互斥锁来调度任务。std::scoped_lock可以简化这种多锁管理的复杂性,确保任务调度的正确性和效率。
5. 总结
std::scoped_lock是C++17标准库中一个非常实用的工具,它通过自动管理多个锁的生命周期,解决了多锁管理中的死锁、异常安全和代码复杂性问题。在实际开发中,合理使用std::scoped_lock可以显著提高代码的可读性、可维护性和健壮性。如果你正在从事多线程编程,std::scoped_lock绝对是一个值得深入了解和使用的工具。
希望这篇文章对你理解std::scoped_lock有所帮助!如果你有任何问题或建议,欢迎在评论区留言。
相关文章:
C++17中的std::scoped_lock:简化多锁管理的利器
文章目录 1. 为什么需要std::scoped_lock1.1 死锁问题1.2 异常安全性1.3 锁的管理复杂性 2. std::scoped_lock的使用方法2.1 基本语法2.2 支持多种互斥锁类型2.3 自动处理异常 3. std::scoped_lock的优势3.1 避免死锁3.2 简化代码3.3 提供异常安全保证 4. 实际应用场景4.1 数据…...
Linux内核实时机制7 - 实时改造机理 - 软中断优化下
Linux内核实时机制7 - 实时改造机理 - 软中断优化下 https://blog.csdn.net/u010971180/article/details/145722641以下分别以Linux4.19、Linux5.4、Linux5.10、Linux5.15 展开分析,深入社区实时改造机理的软中断优化过程。https://blog.csdn.net/weixin_41028621/article/det…...
计算机网络:应用层 —— 文件传送协议 FTP
文章目录 FTP 是什么?FTP 的应用FTP 的基本工作原理主动模式被动模式 总结 FTP 是什么? 将某台计算机中的文件通过网络传送到可能相很远的另一台计算机中,是一项基本的网络应用,即文件传送。 文件传送协议FTP(File T…...
[笔记.AI]如何判断模型是否通过剪枝、量化、蒸馏生成?
以下摘自与DeepSeek-R1在线联网版的对话 一、基础判断维度 技术类型核心特征验证方法剪枝模型参数减少、结构稀疏化1. 检查模型参数量是否显著小于同类标准模型1 2. 分析权重矩阵稀疏性(如非零参数占比<30%)4量化权重/激活值精度降低、推理速度提升1…...
python: SQLAlchemy (ORM) Simple example using mysql in Ubuntu 24.04
mysql sql script: create table School 表 (SchoolId char(5) NOT NULL comment主鍵primary key,學校編號,SchoolName nvarchar(500) NOT NULL DEFAULT comment 學校名稱,SchoolTelNo varchar(8) NULL DEFAULT comment電話號碼,PRIMARY KEY (SchoolId) #主…...
【前端】【nuxt】nuxt优势(MVP开发),转换SSR与SPA模式
Nuxt.js 核心优势 自动化路由系统 无需手动配置路由:在 pages/ 目录下创建 .vue 文件即可自动生成路由,支持动态路由(如 pages/user/[id].vue → /user/:id)。嵌套路由:通过 parent.vue parent/child.vue 目录结构自动…...
洛谷B3619(B3620)
B3619 10 进制转 x 进制 - 洛谷 B3620 x 进制转 10 进制 - 洛谷 代码区: #include<algorithm> #include<iostream> #include<vector> using namespace std;int main(){int n,x;cin >> n >> x;vector<char> arry;while(n){if(…...
基于springboot+vue的酒店管理系统的设计与实现
开发语言:Java框架:springbootJDK版本:JDK1.8服务器:tomcat7数据库:mysql 5.7(一定要5.7版本)数据库工具:Navicat11开发软件:eclipse/myeclipse/ideaMaven包:…...
android调用ffmpeg解析rtsp协议的视频流
文章目录 一、背景二、解析rtsp数据1、C层功能代码2、jni层的定义3、app层的调用 三、源码下载 一、背景 本demo主要介绍android调用ffmpeg中的接口解析rtsp协议的视频流(不解析音频),得到yuv数据,把yuv转bitmap在android设备上显…...
cursor使用记录
一、如何查看自己登录的是哪个账号 操作路径:Cursor -- 首选项 -- Cursor Setting (有快捷键) 二、状态修改为竖排(默认是横排) 默认如图展示,想要像vscode、idea等等在左侧竖着展示 操作路径࿱…...
Java 使用websocket
添加依赖 <!-- WebSocket 支持 --> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId> </dependency>添加配置类 Configuration public class WebSocketConfig {B…...
蓝桥杯 Java B 组之背包问题、最长递增子序列(LIS)
Day 4:背包问题、最长递增子序列(LIS) 📖 一、动态规划(Dynamic Programming)简介 动态规划是一种通过将复杂问题分解成更小的子问题来解决问题的算法设计思想。它主要用于解决具有最优子结构和重叠子问题…...
在PyTorch中使用插值法来优化卷积神经网络(CNN)所需硬件资源
插值法其实就是在已知数据点之间估计未知点的值。通过已知的离散数据点,构造一个连续的曲线函数,预测数据点之间的空缺值是什么并且自动填补上去。 适用场景: 在卷积神经网络(CNN)中的应用场景中,经常遇到计算资源有限,比如显存不够或者处理速度慢,需要用插值来降低计…...
seacmsv9 SQL注入漏洞(报错注入)
一、海洋CMS简介 海洋cms是为解决站长核心需求而设计的视频内容管理系统,一套程序自适应电脑、手机、平板、APP多个终端入口,无任何加密代码、安全有保障,是您最佳的建站工具。——来自seacms官网(简而言之就是专门搭建看片网站的…...
Java 中的内存泄漏问题及解决方案
在 Java 中,内存泄漏(Memory Leak)是指在程序运行过程中,某些对象已经不再使用,但由于引用仍然存在,这些对象无法被垃圾回收器回收,从而导致内存无法释放,最终可能导致系统性能下降甚…...
解决 ERROR: Failed building wheel for vllm Failed to build vllm
1. 完整报错 copying build\lib\vllm\model_executor\layers\fused_moe\configs\E256,N128,device_nameNVIDIA_H100_80GB_HBM3,dtypefp8_w8a8,block_shape[128,128].json -> build\bdist.win-amd64\wheel.\vllm\model_executor\layers\fused_moe\configs error: could not …...
从CNN到Transformer:遥感影像目标检测的未来趋势
文章目录 前言专题一、深度卷积网络知识专题二、PyTorch应用与实践(遥感图像场景分类)专题三、卷积神经网络实践与遥感影像目标检测专题四、卷积神经网络的遥感影像目标检测任务案例【FasterRCNN】专题五、Transformer与遥感影像目标检测专题六、Transfo…...
ecovadis社会企业责任认证
EcoVadis 是一家全球性的企业社会责任 (CSR) 评级机构,旨在通过评估企业在环境、劳工与人权、商业道德和可持续采购等方面的表现,帮助提升其可持续性和社会责任实践。 EcoVadis 认证的核心内容 环境 评估企业在能源消耗、碳排放、废物管理等方面的表现。…...
使用 Docker 部署 Flask 应用
使用 Docker 部署 Flask 应用 一、引言 在现代软件开发中,应用的部署和环境管理是至关重要的环节。传统的部署方式常常会遇到 “在我机器上能运行,在你机器上不行” 的问题,而 Docker 的出现很好地解决了这个痛点。Docker 是一个用于开发、部署和运行应用程序的开放平台,…...
istio介绍补充以及使用篇
istio介绍补充以及使用篇 前言 介绍istio各个组件创建istio的方式手动注入自动注入side car 使用istio做流量灰度如有需要收藏的看官,顺便也用发财的小手点点赞哈,如有错漏,也欢迎各位在评论区评论! 前言 前篇istio介绍了引入ist…...
DeepSeek 助力 Vue 开发:打造丝滑的 键盘快捷键(Keyboard Shortcuts)
前言:哈喽,大家好,今天给大家分享一篇文章!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏关注哦 💕 目录 Deep…...
【JavaScript】《JavaScript高级程序设计 (第4版) 》笔记-Chapter19-表单脚本
十九、表单脚本 表单脚本 JavaScript 较早的一个用途是承担一部分服务器端表单处理的责任。虽然 Web 和 JavaScript 都已经发展了很多年,但 Web 表单的变化不是很大。由于不能直接使用表单解决问题,因此开发者不得不使用JavaScript 既做表单验证…...
如何使用深度学习进行手写数字识别(MNIST)
目录 手写数字识别(MNIST)1. 导入必要的库2. 加载和预处理数据3. 构建模型4. 编译模型5. 训练模型6. 评估模型7. 可视化训练过程(可选)代码说明运行环境总结当然可以!下面是一个使用Python和Keras(TensorFlow后端)实现的简单深度学习案例——手写数字识别(MNIST数据集)…...
【UCB CS 61B SP24】Lecture 5 - Lists 3: DLLists and Arrays学习笔记
本文内容为构建双向循环链表、使用 Java 的泛型将其优化为通用类型的链表以及数组的基本语法介绍。 1. 双向链表 回顾上一节课写的代码,当执行 addLast() 与 getLast() 方法时需要遍历链表,效率不高,因此可以添加一个指向链表末尾的索引&am…...
Unity Excel导表工具转Lua文件
思路介绍 借助EPPlus读取Excel文件中的配置数据,根据指定的不同类型的数据配置规则来解析成对应的代码文本,将解析出的字符串内容写入到XXX.lua.txt文件中即可 EPPlus常用API //命名空间 using OfficeOpenXml;//Excel文件路径 var fileExcel new File…...
kafka消费能力压测:使用官方工具
背景 在之前的业务场景中,我们发现Kafka的实际消费能力远低于预期。尽管我们使用了kafka-go组件并进行了相关测试,测试情况见《kafka-go:性能测试》这篇文章。但并未能准确找出消费能力低下的原因。 我们曾怀疑这可能是由我的电脑网络带宽问题或Kafka部…...
算法题(74):Pow(x,n)
审题: 需要我们计算出x(double类型)的n次幂,并返回 思路: 方法一:递归 (1)首先我们的n分为正和负,对于负的我们需要将n转为正的进行运算后,用1.0除以运算结果…...
windwos与linux环境下Iperf3带宽测试工具的安装、使用
目录 一、前言 二、windows 2.1下载 2.2安装 2.3使用 2.3.1服务端 2.3.2客户端 2.3.3输出内容 1.客户端 2.服务端 2.4.相关命令 三、linux 3.1安装 3.2使用 1.服务端 2.客户端 3.输出内容 1.客户端 2.服务端 一、前言 在数字化浪潮下,网络性能…...
GCC编译器(含预处理/编译/汇编/链接四阶段详解)
GCC编译器(含预处理/编译/汇编/链接四阶段详解) 1. 预处理阶段(生成 .i 文件)2. 编译阶段(生成 .s 文件)3. 汇编阶段(生成 .o 文件)4. 链接阶段(生成可执行文件ÿ…...
20250221 NLP
1.向量和嵌入 https://zhuanlan.zhihu.com/p/634237861 encoder的输入就是向量,提前嵌入为向量 二.多模态文本嵌入向量过程 1.文本预处理 文本tokenizer之前需要预处理吗? 是的,文本tokenizer之前通常需要对文本进行预处理。预处理步骤可…...
Mac M3/M4 本地部署Deepseek并集成vscode
Mac 部署 使用傻瓜集成平台ollama,ollama平台依赖于docker,Mac的M3/M4 因doesn’t have VT-X/AMD-v enabled 所以VB,VM无法使用,导致docker无法启动,需要使用docker的替代品podman, 它完全兼容docker brew install p…...
flink使用demo
1、添加不同数据源 package com.baidu.keyue.deepsight.memory.test;import com.baidu.keyue.deepsight.memory.WordCount; import com.baidu.keyue.deepsight.memory.WordCountData; import org.apache.flink.api.common.RuntimeExecutionMode; import org.apache.flink.api.…...
目标检测中单阶段检测模型与双阶段检测模型详细对比与说明
《------往期经典推荐------》 一、AI应用软件开发实战专栏【链接】 项目名称项目名称1.【人脸识别与管理系统开发】2.【车牌识别与自动收费管理系统开发】3.【手势识别系统开发】4.【人脸面部活体检测系统开发】5.【图片风格快速迁移软件开发】6.【人脸表表情识别系统】7.【…...
简识Spring创建Bean方式和设计模式
一、理论解释: Spring在创建Bean时主要有四种方式,这些方式分别涉及到了不同的设计模式。以下是具体的创建方式及对应的设计模式: 通过反射调用构造方法创建Bean: 方式:在Spring的配置文件中,使用<bean…...
空字符串““、空白字符串“ “和 null 三者的区别
空字符串、空白字符串和 null 三者的区别表格: 类型定义示例长度是否有值空字符串字符串长度为 0,但不是 null,即存在一个有效的空字符串对象。""0有值(空值)空白字符串字符串包含空格、制表符等空白字符&a…...
agent和android怎么结合:健康助手,旅游助手,学习助手
agent和android怎么结合:健康助手,旅游助手,学习助手 创新点 智能交互创新:提出全新的agent - Android交互模式,如基于手势、语音、眼动等多模态融合的交互方式。例如让agent能够同时理解用户的语音指令和手势动作,在Android设备上提供更加自然和高效的交互体验,比如在…...
1.16作业
1 进注册界面,第一次以为抓包选把isadmin ture了就好 第二次尝试,勾选is admin,有需要invitecode(经典) 2 p r**5 r**4 - r**3 r**2 - r 2023 q r**5 - r**4 r**3 - r**2 r 2023 n 25066797992811602609904…...
上帝之眼——nmap
nmap介绍 Nmap(网络映射器)是一款广受欢迎的网络探测和安全评估工具,被誉为“上帝之眼”。它以其强大的扫描功能和广泛的应用场景,成为系统管理员和安全专家手中的得力助手。本文将对Nmap进行详细介绍,包括其优点、基本…...
6.日常英语笔记
It’s a pity that my English hasn’t improved much, and I’m not able to chat with you freely. lung 肺 pulmonary 医学中的肺部相关的 pulmonary disease 肺部疾病 pneumonia 肺炎 pulmonary inflammation 肺炎 stick on the wall 贴到墙上 paste on the wall faint w…...
工业路由器和工业交换机,打造高效稳定的工业网络?
工业路由器和工业交换机各有千秋,但如何将它们完美结合,构建稳定高效的工业网络?答案就在这里! 工业物联网(IIoT)是高效、稳定的工业网络成为智慧工厂、工业自动化和远程监控等场景的基础支撑。工业路由器…...
[c++]--类和对象
目录 前言 一、类的定义 1.类定义格式 2.访问限定符 3.类域 二、实例化 1.实例化概念 2.对象大小 三、this指针 四、C和C语言实现Stack对比 五、类的默认成员函数 1.构造函数 2.析构函数 3.拷贝构造函数 4.赋值运算符重载 4.1.运算符重载 4.2.赋值运算符重载 5.取地址运算符重载…...
图论 之 迪斯科特拉算法求解最短路径
文章目录 题目743.网络延迟时间3341.到达最后一个房间的最少时间I 求解最短路径的问题,分为使用BFS和使用迪斯科特拉算法,这两种算法求解的范围是有区别的 BFS适合求解,边的权值都是1的图中的最短路径的问题 图论 之 BFS迪斯科特拉算法适合求…...
Linux中[root@localhost ~]#
root :当前登录用户 :分隔符 localhost :主机名。当前电脑的名字 ~:当前用户所在的位置 #:命令提示符,从这个位置开始可以输入命令 另一个提示符是$ 如果是 root ,则提示# 如果是普…...
DuodooBMS源码解读之 sale_delivery模块
发货通知单下载功能操作手册 一、功能概述 该代码实现了发货通知单的下载功能,用户可以选择要下载的发货通知单,系统将生成包含发货通知单详细信息的 Excel 文件供用户下载。 二、文件结构及说明 sale_delivery/controllers/download.py 定义了一个 …...
uniapp引入uview组件库(可以引用多个组件)
第一步安装 npm install uview-ui2.0.31 第二步更新uview npm update uview-ui 第三步在main.js中引入uview组件库 第四步在uni.scss中引入import "uview-ui/theme.scss"样式 第五步在文件中使用组件...
SpringCloud-Eureka初步使用
什么是REST是一组用于规范资源在网络中转移的表现形式软件架构设计风格.简单来说就是客户端和服务器之间的一种交互形式 什么是RESTful,满足了REST风格的接口或者程序,RESTful API是其中的接口,spring中提供了RestTemplate这个类,他强制执行了REST的规范,包括使用HTTP协议的状…...
【gitlab】认识 持续集成与部署
持续集成(CI)与持续部署(CD) 1. 什么是持续集成(CI)? 持续集成(Continuous Integration,CI)是一种软件开发实践,强调开发人员频繁地将代码提交到…...
机器学习,我们主要学习什么?
机器学习的发展历程 机器学习的发展历程,大致分为以下几个阶段: 1. 起源与早期探索(20世纪40年代-60年代) 1949年:Hebb提出了基于神经心理学的学习机制,开启了机器学习的先河1950年代:机器学习的…...
React 高阶组件的优缺点
React 高阶组件的优缺点 优点 1. 代码复用性高 公共逻辑封装:当多个组件需要实现相同的功能或逻辑时,高阶组件可以将这些逻辑封装起来,避免代码重复。例如,多个组件都需要在挂载时进行数据获取操作,就可以创建一个数…...
算法1-4 数楼梯
题目描述 楼梯有 N 阶,上楼可以一步上一阶,也可以一步上二阶。 编一个程序,计算共有多少种不同的走法。 输入格式 一个数字,楼梯数。 输出格式 输出走的方式总数。 输入输出样例 输入 #1 4 输出 #1 5 说明/提示 对于…...