C++学习0.2: RAII
引用:
【代码质量】RAII在C++编程中的必要性_raii 在c++中的重要性-CSDN博客
C++ RAII典型应用之lock_guard和unique_lock模板_raii lock-CSDN博客
前言:
常用的线程间同步/通信(IPC)方式有锁(互斥锁、读写锁、自旋锁)、屏障、条件变量、信号量、消息队列。其中锁一种最常用的一种IPC,用于对多个线程共享的资源进行保护,达到线程互斥访问资源的目的。以互斥锁为例,其中最常见的异常而且是致命的问题是——“死锁”。
死锁(DeadLock) 是指两个或者两个以上的进程(线程)在执行过程中,因争夺资源而造成的一种互相等待的现象,导致两者的任务都无法继续执行下去,直至重新执行程序。
基于RAII(Resource Acquisition Is Initialization)设计理念,C++ 11引入了lock_guard和unique_lock类模板,以尽可能避免死锁产生。
2 lock_guard
lock_guard是C++ 11引入的一个互斥锁类模板。lock_guard基于RAII设计理念,将互斥锁的作用范围和(对象)作用域绑定,函数退出作用域后,自动释放锁资源。避免忘记解锁造成的死锁现象。
lock_guard具有如下特点:
- 创建
lock_guard对象,即获取互斥锁权限,并上锁- 作用域中途不能解锁
- 退出
lock_guard对象作用域后,自动解锁lock_guard锁不能复制且不能移动,禁止拷贝构造和移动构造
3 lock_guard使用
lock_guard使用比较简单:
- 首先需要包含
mutex头文件- 然后创建一个锁实例
mutex- 在需要加锁的作用域内,创建以锁示例
mutex作为形参的lock_guard对象
伪代码实现过程:
#include <mutex> /* for std::mutex std::lock_guard */std::mutex mutex;void func(void)
{const std::lock_guard<std::mutex> lock(mutex);/* todo,上锁区域;无需手动解锁,*/
}
写个例子,代码实现功能:
- 创建两个线程
- 线程分别对全局变量访问,并输出到终端
- 期望结果,线程1输出结果“ 1 2 3 4 5”,线程2输出结果“5 4 3 2 1”
#include <stdio.h>
#include <thread>
#include <mutex>
#include <iostream>
#include <unistd.h>
#include "pthread.h" #define USE_MUTEX 1 /* 是否使用互斥锁,使用,0不使用 */#if USE_MUTEX
std::mutex s_mutex;
#endifstatic int8_t g_count = 0;void *thread0_entry(void *data)
{uint8_t i =0;#if USE_MUTEXconst std::lock_guard<std::mutex> lock(s_mutex);
#endiffor (i = 0;i < 5;i++){g_count ++;printf("%d ", g_count);usleep(100);}printf("\r\n");
}void *thread1_entry(void *data)
{uint8_t i =0;#if USE_MUTEXconst std::lock_guard<std::mutex> lock(s_mutex);
#endiffor (i = 0;i < 5;i++){printf("%d ", g_count);g_count--;usleep(100);}printf("\r\n");
}int main(int argc, char **argv)
{pthread_t thread0;pthread_t thread1; void *retval; pthread_create(&thread0, NULL, thread0_entry, NULL);pthread_create(&thread1, NULL, thread1_entry, NULL);pthread_join(thread0, &retval);pthread_join(thread1, &retval);return 0;}
分别编译启用锁和不启用锁的版本,并打印出程序输出。
#不开启锁版本
chenhaoxu@chenhaoxu-VirtualBox:~/work/test/cpp$ ./test
thread 1: thread 2: 0 0 1 1 02 1 0 1 1#开启锁版本
chenhaoxu@chenhaoxu-VirtualBox:~/work/test/cpp$ ./test
thread 1: 0 1 2 3 4
thread 2: 5 4 3 2 1
chenhaoxu@chenhaoxu-VirtualBox:~/work/test/cpp$
4 unique_lock
unique_lock 是 lock_guard 的衍生版,除了具备lock_guard的完整功能,还增加了自身特有的功能,以适应一些lock_guard无法实现的复杂加锁场景。与lock_guard,相比,unique_lock增加的特性包括:
- 任意时候上锁(指定第二个参数为
std::defer_lock),非创建即上锁
void fun0(void)
{std::unique_lock<std::mutex> ulock(mutex, std::defer_lock); /* 创建对象,不上锁 *//* todo */guard.lock(); /* 上锁 *//* 退出作用域,自动解锁 */
}
- 提供解锁接口
unlock,可以中途解锁,非等退出作用域后才解锁
void fun1(void)
{std::unique_lock<std::mutex> ulock(mutex);/* todo */guard.unlock(); /* 解锁 *//* todo */guard.lock(); /* 继续上锁 *//* 退出作用域,自动解锁 */
}
- 不可复制,但可移动
/* lock_guard 不可复制,不可移动 */
std::lock_guard<std::mutex> lock0(mutex);
std::lock_guard<std::mutex> lock1 = lock0; /* error */
std::lock_guard<std::mutex> lock1 = std::move(lock0); /* error *//* unique_lock 不可复制,可以移动 */
std::unique_lock<std::mutex> ulock0(mutex);
std::unique_lock<std::mutex> ulock1 = ulock0; /* error */
std::unique_lock<std::mutex> ulock1 = std::move(ulock0); /* ok */
使用原则:
lock_guard使用简单,效率高;unique_lock使用比较灵活,效率比lock_guard稍微低一点,因为其内部需要维护锁的状态。关于选择使用原则:lock_guard能解决问题的时候,选择lock_guard;否则选择unique_lock。
注意:lock_guard和unique_lock只支持STL的mutex,不支持POSIX标准的mutex(pthread_mutex_t)。至少目前未支持,编译会失败。
相关文章:
C++学习0.2: RAII
引用: 【代码质量】RAII在C编程中的必要性_raii 在c中的重要性-CSDN博客 C RAII典型应用之lock_guard和unique_lock模板_raii lock-CSDN博客 前言: 常用的线程间同步/通信(IPC)方式有锁(互斥锁、读写锁、自旋锁)、…...
k8s,进一步理解Pod
比如,凡是调度、网络、存储,以及安全相关的属性,基本上是Pod 级别的。 这些属性的共同特征是,它们描述的是“机器”这个整体,而不是里面运行的“程序”。比如,配置这个“机器”的网卡(即&#…...
MFC图形函数学习13——在图形界面输出文字
本篇是图形函数学习的最后一篇,相关内容暂告一段落。 在图形界面输出文字,涉及文字字体、大小、颜色、背景、显示等问题,完成这些需要系列函数的支持。下面做简要介绍。 一、输出文本函数 原型:virtual BOOL te…...
【Canvas与雷达】点鼠标可暂停金边蓝屏雷达显示屏
【成图】 【代码】 <!DOCTYPE html> <html lang"utf-8"> <meta http-equiv"Content-Type" content"text/html; charsetutf-8"/> <head><title>点鼠标可暂停金边蓝屏雷达显示屏 Draft1</title><style typ…...
React第十二节组件之间通讯之发布订阅模式(使用pubsub-js插件)
组件之间通讯常用方案 1、通过props 2、通过context 3、通过发布订阅模式 4、通过Redux 后面会有专栏介绍 1、安装 pubsub-js 插件 yarn add pubsub-js 常用的事件 a、发布事件:传入一个自定义事件名称(name),以及要发布的消息内…...
Vue3安装 运行教程
本文是综合了所有vue安装教程而成 更细化 更简略 希望对各位读者有所帮助! Vue安装 1. Vue-cli脚手架安装 安装vue的方式有很多 我们这里选择npm方式安装vue npm方式 npm方式安装vue,详细介绍见下文。 1.node.js安装和配置 安装npm 需要安装note.js&…...
MySQL:约束constraint
约束就是表中数据的限制条件. 表在设计的时候加入约束的目的是为了保证表中记录的完整性和有效性,如用户表有些列的值(手机号)不能为空,有些列的值(身份证号)不能重复。 主键约束(primary key) PK MySQL主…...
使用Rufus制作Ubuntu需要注意
在使用Rufus制作Ubuntu启动盘并进行BIOS设置时,需要注意以下几点: 关闭RST(英特尔 快速存储技术):在BIOS设置中,如果电脑启用了RST功能,需要将其关闭。因为Ubuntu可能无法检测到硬盘&a…...
探索Go语言的高级特性:性能分析与安全性
Go语言性能分析与安全性 引言 Go语言因其高效的并发特性、简洁的语法和强大的工具链而受到广泛欢迎。在实际开发中,性能分析和安全性是需要特别关注的两个方面。本文将深入探讨Go语言中的性能分析工具和安全性考虑,帮助开发者编写高效、安全的Go应用程…...
SearchSploit配合gcc的使用
渗透测试中,SearchSploit是一个非常有用的工具,用于在Exploit数据库中搜索漏洞利用代码。其使用方法如下: 安装SearchSploit:首先确保你的系统中已经安装了Kali Linux,因为SearchSploit是Kali Linux的一部分。如果没有…...
无人机设计:云台挂载!
一、无人机云台挂载设置 安装与固定 将云台固定到无人机的挂载点上,通常需要使用专用的固定架和螺丝等工具。 确保云台与无人机之间的连接牢固,避免在飞行过程中出现松动或脱落的情况。 连接与调试 将云台与无人机之间的连接线缆(如电源…...
Spring Native适用场景、代理使用及测试部署策略
文章目录 1. Spring Native 适用的应用程序2. 在 Spring Native 中使用代理3. 测试和部署 Spring Native 应用测试部署 1. Spring Native 适用的应用程序 微服务:微服务架构中每个服务都相对独立,快速启动时间和较低的资源消耗对于提高部署效率和服务响…...
LeetCode—11. 盛最多水的容器(中等)
题目描述: 给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。 找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。 返回容器可以储存的最大水量。 说明:…...
第一部分:入门准备 1.欢迎来到新手村 --[JavaScript 新手村:开启编程之旅的第一步]
为什么学习 JavaScript? 学习 JavaScript 有多个重要的理由,它在现代 Web 开发中扮演着不可或缺的角色。以下是几个关键原因: 1. 广泛的应用 JavaScript 是唯一可以在浏览器端直接运行的编程语言,几乎所有的网站和Web应用都使用…...
BERT的中文问答系统50
我们将对BERT的中文问答系统48-1代码进行以下改进: 1.增加时间日期和日历功能:在GUI中增加显示当前时间和日期的功能,并提供一个日历组件。 2.增加更多模型类型:增加娱乐、电脑、军事、汽车、植物、科技、历史(朝代、皇帝)、名人、生活(出行、菜品、菜谱、居家),法律、…...
深入解析CMake中的find_package命令:用法、特性及版本依赖问题
深入解析CMake中的find_package命令:用法、特性及版本依赖问题 在现代软件开发中,CMake作为一个强大的构建系统,广泛应用于跨平台项目的管理与编译。find_package是CMake中一个核心命令,用于查找并配置项目所依赖的外部库或包。本…...
【OpenDRIVE_Python】使用python脚本输出OpenDRIVE数据中含有隧道tunnel的道路ID和隧道信息
示例代码说明: 遍历OpenDRIVE数据中每条道路Road,若Road中存在隧道tunnel属性,则将该道路ID和包含的所有隧道信息输出到xml文件中。 import xml.dom.minidom from xml.dom.minidom import parse from xml.dom import Node import sys import os # 读取…...
SIP系列五:HTTP(SIP)鉴权
我的音视频/流媒体开源项目(github) SIP系列目录 目录 一、基本认证(basic) 二、摘要认证(digest) 1、摘要认证(digest) RFC 2069 2、摘要认证(digest) RFC 2617 2.1、未定义qop字段或值为"(空) 2.2、qop值为"auth" 2.3、qop值为"auth-int&quo…...
mysql json整数数组去重 整数数组精确查找并删除相应数据
都是针对整数数组 。低版本可用。懒得去查找资料的可以参考下。 json整数数组查找具体数据修改或者删除: update saas_new_tms.eda_logistics_limit set service_attribute json_remove(service_attribute,json_unquote(json_search(replace(service_attribute,…...
【5G】技术组件 Technology Components
5G的目标设置非常高,不仅在数据速率上要求达到20Gbps,在容量提升上要达到1000倍,还要为诸如大规模物联网(IoT, Internet of Things)和关键通信等新服务提供灵活的平台。这些高目标要求5G网络采用多种新技术…...
web vue 项目 Docker化部署
Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage):…...
R语言AI模型部署方案:精准离线运行详解
R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...
在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:
在 HarmonyOS 应用开发中,手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力,既支持点击、长按、拖拽等基础单一手势的精细控制,也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档,…...
leetcodeSQL解题:3564. 季节性销售分析
leetcodeSQL解题:3564. 季节性销售分析 题目: 表:sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...
12.找到字符串中所有字母异位词
🧠 题目解析 题目描述: 给定两个字符串 s 和 p,找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义: 若两个字符串包含的字符种类和出现次数完全相同,顺序无所谓,则互为…...
JDK 17 新特性
#JDK 17 新特性 /**************** 文本块 *****************/ python/scala中早就支持,不稀奇 String json “”" { “name”: “Java”, “version”: 17 } “”"; /**************** Switch 语句 -> 表达式 *****************/ 挺好的ÿ…...
dify打造数据可视化图表
一、概述 在日常工作和学习中,我们经常需要和数据打交道。无论是分析报告、项目展示,还是简单的数据洞察,一个清晰直观的图表,往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server,由蚂蚁集团 AntV 团队…...
深度学习之模型压缩三驾马车:模型剪枝、模型量化、知识蒸馏
一、引言 在深度学习中,我们训练出的神经网络往往非常庞大(比如像 ResNet、YOLOv8、Vision Transformer),虽然精度很高,但“太重”了,运行起来很慢,占用内存大,不适合部署到手机、摄…...
学习一下用鸿蒙DevEco Studio HarmonyOS5实现百度地图
在鸿蒙(HarmonyOS5)中集成百度地图,可以通过以下步骤和技术方案实现。结合鸿蒙的分布式能力和百度地图的API,可以构建跨设备的定位、导航和地图展示功能。 1. 鸿蒙环境准备 开发工具:下载安装 De…...
Qt Quick Controls模块功能及架构
Qt Quick Controls是Qt Quick的一个附加模块,提供了一套用于构建完整用户界面的UI控件。在Qt 6.0中,这个模块经历了重大重构和改进。 一、主要功能和特点 1. 架构重构 完全重写了底层架构,与Qt Quick更紧密集成 移除了对Qt Widgets的依赖&…...
