C++11并发与多线程笔记(12) windows临界区、其他各种mutex互斥量
C++11并发与多线程笔记(12) windows临界区、其他各种mutex互斥量
- 1、windows临界区
- 2、自动析构技术
- 3、递归独占互斥量 std::recursive_mutex
- 4、带超时的互斥量 std::timed_mutex 和 std::recursive_timed_mutex
- 4.1 std::timed_mutex:是带超时的独占互斥量
- 4.2 std::recursive_timed_mutex:是带超时的递归独占互斥量
1、windows临界区
Windows临界区,同一个线程是可以重复进入的,但是进入的次数与离开的次数必须相等。
C++互斥量则不允许同一个线程重复加锁 (相同的mutex变量不容许连续调用)。
windows临界区是在windows编程中的内容,了解一下即可,效果几乎可以等同于c++11的mutex
包含**#include <windows.h>**
windows中的临界区同mutex一样,可以保护一个代码段。但windows的临界区可以进入多次,离开多次,但是进入的次数与离开的次数必须相等,不会引起程序报异常出错。
#include <iostream>
#include <thread>
#include <list>
#include <mutex>
#include <Windows.h>#define __WINDOWSJQ_using namespace std;class A
{
public:// 把收到的消息传入队列void inMsgRecvQueue(){for (size_t i = 0; i < 10000; ++i){cout << "收到消息,并放入队列 " << i << endl;
//windows开关
#ifdef __WINDOWSJQ_ EnterCriticalSection(&my_winsec); // 进入临界区//EnterCriticalSection(&my_winsec); // 可以再次进入临界区,程序不会出错msgRecvQueue.push_back(i);LeaveCriticalSection(&my_winsec); // 离开临界区//LeaveCriticalSection(&my_winsec); // 如果进入两次,必须离开两次不会报错
#elsemy_mutex.lock();msgRecvQueue.push_back(i);my_mutex.unlock();
#endif // __WINDOWSJQ_}cout << "消息入队结束" << endl;}// 从队列中取出消息void outMsgRecvQueue(){for (size_t i = 0; i < 10000; ++i){
#ifdef __WINDOWSJQ_EnterCriticalSection(&my_winsec); // 进入临界区if (!msgRecvQueue.empty()){// 队列不为空int num = msgRecvQueue.front();cout << "从消息队列中取出 " << num << endl;msgRecvQueue.pop_front();}else{// 消息队列为空cout << "消息队列为空 " << endl;}LeaveCriticalSection(&my_winsec); // 离开临界区
#elsemy_mutex.lock();if (!msgRecvQueue.empty()){// 队列不为空int num = msgRecvQueue.front();cout << "从消息队列中取出 " << num << endl;msgRecvQueue.pop_front();my_mutex.unlock();}else{// 消息队列为空cout << "消息队列为空 " << endl;my_mutex.unlock();}
#endif // __WINDOWSJQ_}cout << "消息出队结束" << endl;}A(){
#ifdef __WINDOWSJQ_InitializeCriticalSection(&my_winsec); // 用临界区之前要初始化
#endif // __WINDOWSJQ_}private:list<int> msgRecvQueue;mutex my_mutex;#ifdef __WINDOWSJQ_CRITICAL_SECTION my_winsec; // windows中的临界区,非常类似C++11中的mutex,使用之前必须初始化
#endif // __WINDOWSJQ_};int main()
{A myobj;thread myInMsgObj(&A::inMsgRecvQueue, &myobj);thread myOutMsgObj(&A::outMsgRecvQueue, &myobj);myInMsgObj.join();myOutMsgObj.join();getchar();return 0;
}
2、自动析构技术
C++:lock_guard防止忘了释放信号量,自动释放
windows:可以写个类自动释放临界区
//本类用于自动释放windows下的临界区,防止忘记LeaveCriticalSection导致死锁情况的发生
class CWinLock {//RALL类
public:CWinLock(CRITICAL_SECTION *pCritmp)//构造函数{my_winsec =pCritmp;EnterCriticalSection(my_winsec);//进入}~CWinLock()//析构函数{LeaveCriticalSection(my_winsec);//离开}
private:CRITICAL_SECTION *my_winsec;
};class A
{
public:// 把收到的消息传入队列void inMsgRecvQueue(){for (size_t i = 0; i < 10000; ++i){cout << "收到消息,并放入队列 " << i << endl;
//windows开关
#ifdef __WINDOWSJQ_ CWinLock wlock(&my_winsec);//调用msgRecvQueue.push_back(i);
#elsemy_mutex.lock();msgRecvQueue.push_back(i);my_mutex.unlock();
#endif // __WINDOWSJQ_}cout << "消息入队结束" << endl;}
};
上述这种类RAII类(Resource Acquisition is initialization),即资源获取及初始化。容器,智能指针属于这种类。
3、递归独占互斥量 std::recursive_mutex
- std::mutex: 独占式互斥量,自己lock时别人lock不了
- std::recursive_mutex:允许在同一个线程中同一个互斥量多次被 lock(),(但是递归加锁的次数是有限制的,太多可能会报异常),效率要比mutex低。
void testfunc1(){std::lock_guard<std::mutex> sbguard(my_mutex);//...干各种事情testfunc2();//多次加锁,异常
}
void testfunc2(){std::lock_guard<std::mutex> sbguard(my_mutex);//...干各种另外一些事情
}
如果你真的用了 recursive_mutex 要考虑代码是否有优化空间,如果能调用一次 lock()就不要调用多次。
4、带超时的互斥量 std::timed_mutex 和 std::recursive_timed_mutex
4.1 std::timed_mutex:是带超时的独占互斥量
1. try_lock_for():等待一段时间
如果拿到了锁,或者超时了未拿到锁,就继续执行(有选择执行)如下:
std::chrono::milliseconds timeout(100);
if (my_mymutex.try_lock_for(timeout)){//......拿到锁返回turemy_mymutex.unlock();//用完了要解锁
}else{//没拿到锁,不会卡着,流程继续往下走
}
2. try_lock_until():参数是一个未来的时间点
在这个未来的时间没到的时间内,如果拿到了锁头,流程就走下来,如果时间到了没拿到锁,流程也可以走下来。
std::chrono::milliseconds timeout(100);
if (my_mymutex.try_lock_until(chrono::steady_clock::now() + timeout)){//......拿到锁返回turemy_mymutex.unlock();//用完了要解锁
}
else{//没拿到锁,不会卡着,流程继续往下走
}
两者的区别就是一个参数是时间段,一个参数是时间点
4.2 std::recursive_timed_mutex:是带超时的递归独占互斥量
允许同一个线程多次获取这个互斥量
相关文章:
C++11并发与多线程笔记(12) windows临界区、其他各种mutex互斥量
C11并发与多线程笔记(12) windows临界区、其他各种mutex互斥量 1、windows临界区2、自动析构技术3、递归独占互斥量 std::recursive_mutex4、带超时的互斥量 std::timed_mutex 和 std::recursive_timed_mutex4.1 std::timed_mutex:是带超时的…...
[MAUI]在.NET MAUI中实现可拖拽排序列表
文章目录 创建可拖放控件创建绑定服务类拖拽(Drag)拖拽悬停,经过(DragOver)释放(Drop) 创建页面元素最终效果项目地址 .NET MAUI 中提供了拖放(drag-drop)手势识别器,允许用户通过拖…...
Linux 内核内存管理 pfn_to_online_page宏
文章目录 一、Memory Hotplug1.1 简介1.2 热插拔事件通知机制 二、pfn_to_online_page2.1 pfn_to_online_page2.2 pfn_to_section_nr2.3 online_section_nr 参考资料 一、Memory Hotplug 1.1 简介 Linux 内存热插拔(Memory Hotplug)是指在运行时动态增…...
『C语言初阶』第八章 -结构体
前言 今天小羊又来给铁汁们分享关于C语言的结构体,在C语言中,结构体类型属于一种构造类型(其他的构造类型还有:数组类型,联合类型),今天我们主要简单了解一下结构体。 一、结构体是什么&#x…...
chatgpt汇编,两个关于chatgpt的问题
1.用C写一个高级的可自主学习的AI语言模型 编写一个高级的可自主学习的AI语言模型是一个复杂且庞大的工程,需要深入的专业知识和大量的时间精力。下面是一个简化的示例,演示如何使用C实现一个基本的可自主学习的AI语言模型。 首先,你需要定…...
ps丢失d3dcompiler_47.dll怎么办,启动无反应,分享三个解决方法
d3dcompiler_47.dll64位是windows系统中重要的dll文件,缺少了它可能会引起部分软件或者游戏不能运行。 如果系统出现“找不到d3dcompiler_47.dll”或“d3dcompiler_47.dll丢失”等错误信息,那么我们就该着手修复它。 先带了解一下d3dcompiler_47.dll是什…...
第三章nginx详解
nginx:高性能,轻量级的web服务软件。 特点: 1,稳定性高。(没有apache稳定) 2,系统资源消耗地较低。(处理http请求的并发能力非常高,单台物理服务器可以处理30000-5000…...
【二叉树前沿篇】树
【二叉树前沿篇】树 1 树的概念2. 树的相关概念3. 树的表示4. 树在实际中的运用(表示文件系统的目录树结构) 1 树的概念 树是一种非线性的数据结构,它是由n(n>0)个有限结点组成一个具有层次关系的集合。把它叫做树是…...
python3 0基础学习----数据结构(基础+练习)
python 0基础学习笔记之数据结构 📚 几种常见数据结构列表 (List)1. 定义2. 实例:3. 列表中常用方法.append(要添加内容) 向列表末尾添加数据.extend(列表) 将可迭代对象逐个添加到列表中.insert(索引,插入内容) 向指定…...
计算机科学中的“旅行商问题”
题目:旅行商问题(Traveling Salesman Problem) 当初为何收藏:我收藏了这个题目是因为它是一个经典而富有挑战性的组合优化问题,涉及到计算机科学、算法设计和实际应用领域。我认为这个问题可以展示出算法设计的重要性…...
QT:自定义控件(Connect使用,子控件连接)
自定义控件封装: 1.添加新文件(设计师界面类),创建子页面 ,放自己想要的控件 2.在主页面中使用子控件 :新建一个widget- ISO21434 组织网络安全管理(二) ISO21434 项目网络安全管理(三) ISO21434 分布式网络安全(四) SO21434 持续进行的网络安全(五) ISO21434 概念阶段网络安全(六)...
Visual Studio 如何放大代码字体的大小
1.打开Visual Studio,新建一个程序,一段代码,为接下去的操作做好准备。单击菜单栏的【工具】选项。 2.在跳出来菜单中找到【选项】(一般在最后一项),然后单击。跳出新的窗口。 3.跳出新的窗口后ÿ…...
Verilog同步FIFO设计
同步FIFO(synchronous)的写时钟和读时钟为同一个时钟,FIFO内部所有逻辑都是同步逻辑,常常用于交互数据缓冲。 异步FIFO:数据写入FIFO的时钟和数据读出FIFO的时钟是异步的(asynchronous) 典型同步FIFO有三部分组成: (1࿰…...
Php“牵手”lazada商品详情页数据采集方法,lazadaAPI接口申请指南
lazada详情接口 API 是开放平台提供的一种 API 接口,它可以帮助开发者获取商品的详细信息,包括商品的标题、描述、图片等信息。在电商平台的开发中,详情接口API是非常常用的 API,因此本文将详细介绍详情接口 API 的使用。 一、la…...
Sentinel 规则持久化
文章目录 Sentinel 规则持久化一、修改order-service服务1.引入依赖2.配置nacos地址 第二步修改非常麻烦,可以略过,直接使用已经打好包的来使用二、修改sentinel-dashboard源码1. 解压2. 修改nacos依赖3. 添加nacos支持4. 修改nacos地址5. 配置nacos数据…...
元宇宙时代超高清视音频技术白皮书关于流媒体协议和媒体传输解读
流媒体协议 元宇宙业务场景对流媒体传输的实时性和互动性提出了更高的要求,这就需要在传统的 RTMP、SRT、 HLS 等基础上增加实时互动的支持。实时互动,指在远程条件下沟通、协作,可随时随地接入、实时地传递虚实融合的多维信息,身…...
【计算机设计大赛】国赛一等奖项目分享——基于多端融合的化工安全生产监管可视化系统
文章目录 一、计算机设计大赛国赛一等奖二、项目背景三、项目简介四、系统架构五、系统功能结构六、项目特色(1)多端融合(2)数据可视化(3)计算机视觉(目标检测) 七、系统界面设计&am…...
深入理解【二叉树】
📙作者简介: 清水加冰,目前大二在读,正在学习C/C、Python、操作系统、数据库等。 📘相关专栏:C语言初阶、C语言进阶、C语言刷题训练营、数据结构刷题训练营、有感兴趣的可以看一看。 欢迎点赞 👍…...
RequestRespons
文章目录 Request&Respons1 Request和Response的概述2 Request对象2.1 Request继承体系2.2 Request获取请求数据2.2.1 获取请求行数据2.2.2 获取请求头数据2.2.3 获取请求体数据2.2.4 获取请求参数的通用方式 2.3 IDEA快速创建Servlet2.4 请求参数中文乱码问题2.4.1 POST请…...
MPNet:旋转机械轻量化故障诊断模型详解python代码复现
目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...
Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...
CMake基础:构建流程详解
目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...
什么是库存周转?如何用进销存系统提高库存周转率?
你可能听说过这样一句话: “利润不是赚出来的,是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业,很多企业看着销售不错,账上却没钱、利润也不见了,一翻库存才发现: 一堆卖不动的旧货…...
Python爬虫(二):爬虫完整流程
爬虫完整流程详解(7大核心步骤实战技巧) 一、爬虫完整工作流程 以下是爬虫开发的完整流程,我将结合具体技术点和实战经验展开说明: 1. 目标分析与前期准备 网站技术分析: 使用浏览器开发者工具(F12&…...
04-初识css
一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...
Java 二维码
Java 二维码 **技术:**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...
push [特殊字符] present
push 🆚 present 前言present和dismiss特点代码演示 push和pop特点代码演示 前言 在 iOS 开发中,push 和 present 是两种不同的视图控制器切换方式,它们有着显著的区别。 present和dismiss 特点 在当前控制器上方新建视图层级需要手动调用…...
掌握 HTTP 请求:理解 cURL GET 语法
cURL 是一个强大的命令行工具,用于发送 HTTP 请求和与 Web 服务器交互。在 Web 开发和测试中,cURL 经常用于发送 GET 请求来获取服务器资源。本文将详细介绍 cURL GET 请求的语法和使用方法。 一、cURL 基本概念 cURL 是 "Client URL" 的缩写…...
