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

13-3_Qt 5.9 C++开发指南_基于QReadWriteLock 的线程同步

使用互斥量时存在一个问题: 每次只能有一个线程获得互斥量的权限。如果在一个程序中有多个线程读取某个变量,使用互斥量时也必须排队。而实际上若只是读取一个变量,是可以让多个线程同时访问的,这样互斥量就会降低程序的性能。

例如,假设有一个数据采集程序,一个线程负责采集数据到缓冲区,一个线程负责读取缓冲区的数据并显示,另一个线程负责读取缓冲区的数据并保存到文件,示意代码如下:

int buffer [100];
QMutex mutex;
void threadDAQ::run()
{...mutex.lock();get_data_and_write_in_buffer(); //数据写入buffermutex.unclock();...
}void threadShow::run()
{...mutex.lock();show_buffer(); //读取buffer里的数据并显示mutex.unclock();...
}void threadSaveFile::run()
{...mutex.lock();Save_buffer_toFile(); //读取buffer里的数据并保存到文件mutex.unclock();...
}

数据缓冲区 buffer 和瓦斥量 mutex 都是全局变量,线程 threadDAO 将数据写到 buffer,线程threadShow 和 threadSaveFile 只是读取 buffer,但是因为使用互斥量,这3个线程任何时候都只能有一个线程可以访问 buffer。而实际上,threadShow 和 threadSaveFile 都只是读取 bufer 的数据,它们同时访问 buffer 是不会发生冲突的。

Qt 提供了 QReadWriteLock 类,它是基于读或写的模式进行代码段锁定的,在多个线程读写一个共享数据时,可以解决上面所说的互斥量存在的问题。

QReadWriteLock 以读或写锁定的同步方法允许以读或写的方式保护一段代码,它可以允许多个线程以只读方式同步访问资源,但是只要有一个线程在以写方式访问资源时,其他线程就必须等待直到写操作结束。

QReadWriteLock 提供以下几个主要的函数:

  • lockForRead(),以只读方式锁定资源,如果有其他线程以写入方式锁定,这个函数会阻塞:
  • lockForWrite(),以写入方式锁定资源,如果本线程或其他线程以读或写模式锁定资源,这个函数就阻塞;
  • unlock(),解锁;
  • tryLockForRead(),是 lockForRead()的非阻塞版本;
  • tryLockForWrite(),是lockForWrite的非阻塞版本。

使用QReadWriteLock,上面的三线程代码可以改写为如下的形式:

int buffer [100];
QReadWriteLock Lock;
void threadDAQ::run()
{...Lock.lockForWrite();get_data_and_write_in_buffer(); //数据写入buffermutex.unclock();...
}void threadShow::run()
{...Lock.lockForRead();show_buffer(); //读取buffer里的数据并显示mutex.unclock();...
}void threadSaveFile::run()
{...Lock.lockForRead();Save_buffer_toFile(); //读取buffer里的数据并保存到文件mutex.unclock();...
}

这样,如果 threadDAQ 没有以 lockForWrite()锁定 Lock,threadShow 和 threadSaveFile 可以同时访问 buffer,否则 threadShow 和 threadSaveFile 都被阻塞;如果 threadShow 和 threadSaveFile 都没有锁定,那么 threadDAQ 能以写入方式锁定,否则 threadDAQ 就被阻塞。

QReadLocker 和 QWriteLocker 是 QReadWriteLock 的简便形式,如同 QMutexLocker 是QMutex 的简便版本一样,无需与unlock()配对使用。使用QReadLocker 和QWriteLocker,则上面的代码改写为:

int buffer [100];
QReadWriteLock Lock;
void threadDAQ::run()
{...QWriteLocker Locker(&Lock);get_data_and_write_in_buffer(); //数据写入buffer...
}void threadShow::run()
{...QReadLocker Locker(&Lock);show_buffer(); //读取buffer里的数据并显示...
}void threadSaveFile::run()
{...QReadLocker Locker(&Lock);Save_buffer_toFile(); //读取buffer里的数据并保存到文件...
}

相关文章:

13-3_Qt 5.9 C++开发指南_基于QReadWriteLock 的线程同步

使用互斥量时存在一个问题: 每次只能有一个线程获得互斥量的权限。如果在一个程序中有多个线程读取某个变量,使用互斥量时也必须排队。而实际上若只是读取一个变量,是可以让多个线程同时访问的,这样互斥量就会降低程序的性能。 例如&#xf…...

opencv04-掩膜

opencv04-掩膜 抠图 #include <iostream> #include <opencv2/highgui/highgui.hpp> #include <opencv2/opencv.hpp> #include <vector> #include <array> #include <algorithm>using namespace std; using namespace cv;int main() {str…...

python解析帆软cpt及frm文件(xml)获取源数据表及下游依赖表

#!/user/bin/evn python import os,re,openpyxl 输入&#xff1a;帆软脚本文件路径输出&#xff1a;帆软文件检查结果Excel#获取来源表 def table_scan(sql_str):# remove the /* */ commentsq re.sub(r"/\*[^*]*\*(?:[^*/][^*]*\*)*/", "", sql_str)# r…...

TypeScript

TypeScript 简称&#xff1a; TS &#xff0c;是 JavaScript 的超集 &#xff0c;简单来说就是&#xff1a; JS 有的 TS 都有 TypeScript Type JavaScript &#xff08;在 JS 基础之上&#xff0c; 为 JS 添加了类型支持 &#xff09; TypeScript 是 微软 开发…...

解决启动vue前端报错:npm ERR! Missing script: “serve“

目录 一、遇到问题 二、出现报错的两个原因 三、解决办法 一、遇到问题 npm ERR! Missing script: "serve" npm ERR! npm ERR! To see a list of scripts, run: npm ERR! npm run npm ERR! A complet...

数据结构 | 线性数据结构——列表

目录 一、无序列表抽象数据类型 二、实现无序列表&#xff1a;链表 2.1 Node类 2.2 UnorderedList类 三、有序列表抽象数据类型 四、实现有序列表 列表是元素的集合&#xff0c;其中每一个元素都有一个相对于其他元素的位置。更具体地说&#xff0c;这种列表成为无序列表…...

【ARM 常见汇编指令学习 6 - bic(位清除), orr(位或), eor(异或)】

文章目录 BIC 指令ORR 位或指令EOR 异或指令 上篇文章&#xff1a;ARM 常见汇编指令学习 5 – arm64汇编指令 wzr 和 xzr 下篇文章&#xff1a;ARM 常见汇编指令学习 7 - LDR 指令与LDR伪指令及 mov指令 BIC 指令 指令格式 bic{条件}{S} Rd&#xff0c;Rn&#xff0c;operan…...

在CSDN学Golang场景化解决方案(EFK分布式日志系统方案)

一&#xff0c;ElasticSearch 分布式集群部署 在 Golang EFK 分布式日志系统方案中&#xff0c;ElasticSearch 是一个分布式搜索引擎和数据存储库&#xff0c;它可以用于存储和搜索大量的日志数据。以下是 ElasticSearch 分布式集群部署的步骤&#xff1a; 下载 ElasticSearc…...

MySQL篇

文章目录 一、MySQL-优化1、在MySQL中&#xff0c;如何定位慢查询?2、SQL语句执行很慢, 如何分析呢&#xff1f;3、了解过索引吗&#xff1f;&#xff08;什么是索引&#xff09;4、索引的底层数据结构了解过嘛 ?5、什么是聚簇索引什么是非聚簇索引 ?6、知道什么是回表查询嘛…...

图数据库Neo4j学习四——Spring Data NEO

1配置 1.1Maven依赖 <!--neo4j --> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-neo4j</artifactId> </dependency>1.2yml配置 spring:data:neo4j:uri: bolt://localhost:76…...

UE虚幻引擎 UTextBlock UMG文本控件超过边界区域以后显示省略号

版本 5.2.1 裁剪 - 剪切 - 剪切到边界 裁剪 - 高级 - 溢出策略 - 省略...

Spring Boot实践五 --异步任务线程池

一、使用Async实现异步调用 在Spring Boot中&#xff0c;我们只需要通过使用Async注解就能简单的将原来的同步函数变为异步函数&#xff0c;Task类实现如下&#xff1a; package com.example.demospringboot;import lombok.extern.slf4j.Slf4j; import org.springframework.s…...

<C语言> 动态内存管理

1.动态内存函数 为什么存在动态内存分配&#xff1f; int main(){int num 10; //向栈空间申请4个字节int arr[10]; //向栈空间申请了40个字节return 0; }上述的开辟空间的方式有两个特点&#xff1a; 空间开辟大小是固定的。数组在声明的时候&#xff0c;必须指定数组的…...

【ASPICE】:学习记录

学习记录 ASPICE中文资料什么是ASPICE过程参考模型 ASPICE全称“Automotive Software Process Improvement and Capability dEtermination”&#xff0c;即“汽车软件过程改进及能力评定”模型框架 ASPICE中文资料 主要资料来源 什么是ASPICE 过程参考模型...

图论--最短路问题

图论–最短路问题 邻接表 /* e[idx]:存储点的编号 w[idx]:存储边的距离&#xff08;权重&#xff09; */ void add(int a, int b, int c) {e[idx] b;ne[idx] h[a];w[idx] ch[a] idx ; }1.拓扑排序 给定一个 n 个点 m 条边的有向图&#xff0c;点的编号是 11 到 n&#xf…...

go 结构体 - 值类型、引用类型 - 结构体转json类型 - 指针类型的种类 - 结构体方法 - 继承 - 多态(interface接口) - 练习

目录 一、结构体 1、python 与 go面向对象的实现&#xff1a; 2、初用GO中的结构体&#xff1a;&#xff08;实例化一个值类型的数据&#xff08;结构体&#xff09;&#xff09; 输出结果不同的三种方式 3、实例化一个引用类型的数据&#xff08;结构体&#xff09; 4、…...

盘点16个.Net开源项目

今天一起盘点下&#xff0c;16个.Net开源项目&#xff0c;有博客、商城、WPF和WinForm控件、企业框架等。&#xff08;点击标题&#xff0c;查看详情&#xff09; 一、一套包含16个开源WPF组件的套件 项目简介 这是基于WPF开发的&#xff0c;为开发人员提供了一组方便使用自…...

记录对 require.js 的理解

目录 一、使用 require.js 主要是为了解决这两个问题二、require.js 的加载三、main.js 一、使用 require.js 主要是为了解决这两个问题 实现 js 文件的异步加载&#xff0c;避免网页失去响应&#xff1b;管理模块之间的依赖性&#xff0c;便于代码的编写和维护。 二、require.…...

minio-分布式文件存储系统

minio-分布式文件存储系统 minio的简介 MinIO基于Apache License v2.0开源协议的对象存储服务&#xff0c;可以做为云存储的解决方案用来保存海量的图片&#xff0c;视频&#xff0c;文档。由于采用Golang实现&#xff0c;服务端可以工作在Windows,Linux, OS X和FreeBSD上。配置…...

Kindling the Darkness: A Practical Low-light Image Enhancer论文阅读笔记

这是ACMMM2019的一篇有监督暗图增强的论文&#xff0c;KinD其网络结构如下图所示&#xff1a; 首先是一个分解网络分解出R和L分量&#xff0c;然后有Restoration-Net和Adjustment-Net分别去对R分量和L分量进一步处理&#xff0c;最终将处理好的R分量和L分量融合回去。这倒是很常…...

(十)学生端搭建

本次旨在将之前的已完成的部分功能进行拼装到学生端&#xff0c;同时完善学生端的构建。本次工作主要包括&#xff1a; 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...

SciencePlots——绘制论文中的图片

文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了&#xff1a;一行…...

Spring Boot 实现流式响应(兼容 2.7.x)

在实际开发中&#xff0c;我们可能会遇到一些流式数据处理的场景&#xff0c;比如接收来自上游接口的 Server-Sent Events&#xff08;SSE&#xff09; 或 流式 JSON 内容&#xff0c;并将其原样中转给前端页面或客户端。这种情况下&#xff0c;传统的 RestTemplate 缓存机制会…...

Cesium1.95中高性能加载1500个点

一、基本方式&#xff1a; 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...

【第二十一章 SDIO接口(SDIO)】

第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...

STM32标准库-DMA直接存储器存取

文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA&#xff08;Direct Memory Access&#xff09;直接存储器存取 DMA可以提供外设…...

【C语言练习】080. 使用C语言实现简单的数据库操作

080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...

大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计

随着大语言模型&#xff08;LLM&#xff09;参数规模的增长&#xff0c;推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长&#xff0c;而KV缓存的内存消耗可能高达数十GB&#xff08;例如Llama2-7B处理100K token时需50GB内存&a…...

技术栈RabbitMq的介绍和使用

目录 1. 什么是消息队列&#xff1f;2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...

return this;返回的是谁

一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请&#xff0c;不同级别的经理有不同的审批权限&#xff1a; // 抽象处理者&#xff1a;审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...