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

[qt] 线程等待与唤醒

 

  • 对于生产者与消费者的数据处理的另一种好的解决方法是使用QWaitCondition类,允许线程在一定的条件下唤醒其他多个线程来共同处理。

一 定义公共变量

  • DataSize: 生产者生产数据的大小
  • BufferSize: 也就是这个缓冲区的大小,每个单元是一个int,也有可能是一个链表,结构体等等。
  • mutex: 为了保证多个线程操作同一块数据时的原子性操作
  • int numUsedBytes: 表示当前已经使用了多少个存储"单元"。
  • int rIndex = 0:由于使用多个消费者线程处理生产者数据,所以为了不重复读取,设置全局变量rIndex用于标识当前读取到缓冲区的位置。
const int DataSize=1000;
const int BufferSize=80;
int buffer[BufferSize];
QWaitCondition bufferEmpty;
QWaitCondition bufferFull;
QMutex mutex;
int numUsedBytes = 0;
int index = 0;

二 生产者

  • 同样的继承QThread,在run函数中完成生产者的工作。
  • 首先进入for循环就必须对整个for循环中的操作进行加锁。只需要记住如果有一个变量在生产者和消费者线程中都会被改变,那么这个变量存在的地方就必须加锁。比如这里的numUseBytes;
  • if(numUsedBytes == BufferSize) 如果已经使用的单元等于当前缓冲区单元数,那么就必须等待消费者处理
  • bufferEmpty.wait(&mutex):等待“缓冲区有空位”,也就是当缓冲区写满时,等待消费者线程读取(处理)缓冲区,wait()函数会将互斥量mutex在此解锁并且QWaitComdition在此等待。这个函数的原型如下:
  1. 首先传入的参数是一个被锁定的互斥量,如果传入时的互斥量不是被锁定的,或者出现递归锁的情况,那么wait会立刻返回。
  2. 参数2传入的是等待时间
  3. 首先我们要知道的是在这QWaitComdition在这里等待的结束条件。如果在其他线程调用了QWaitComdition的方法wakeOne或者wakeAll,那么这个函数就会返回true
  4. 由于第二个参数默认是永不超时,但是当我们设置了超时,并且在超时后,并没有被唤醒,那么就会返回false,
  5. 无论这个返回的是true还是false,再返回前QWaitComdition都会将QMutex重新设置为锁定状态。
  • buffer[i%BufferSize]= numUsedBytes:生产者向缓冲区写入数据
  •  numUsedBytes++:让使用过的缓冲单元数量加一
  •  bufferFull.wakeAll():唤醒所有等待QWaitCondition的线程。
  • 对于wakeOne是随机唤醒一个等待线程,而wakeAll则是唤醒所有等待线程。

bool QWaitCondition::wait(QMutex *mutex,unsigned long time = ULONG_MAX);

void Producer::run()
{for(int i=0;i<DataSize;i++){mutex.lock();if(numUsedBytes == BufferSize){bufferEmpty.wait(&mutex);}buffer[i%BufferSize] = numUsedBytes;numUsedBytes++;mutex.unlock();bufferFull.wakeAll();}
}

三 消费者

  • 首先我们判断当可用的数据为0时,就需要等待生产者来激活QWaitCondition
  • 当缓冲单元有可用的数据时,我们读取当前缓冲单元中的数据,并对这个index下标进行处理。
  • 最后我们徐亚将numUsedBytes减一,也就是缓冲区已经用过的数据-1。
  • bufferEmpty.wakAll:激活所有等待缓冲区有空位的条件线程
void Consumer::run()
{Q_FOREVER{mutex.lock();while (numUsedBytes == 0) { // 确保缓冲区不为空bufferFull.wait(&mutex, QDeadlineTimer::Forever);}qDebug()<<currentThreadId()<<index<<buffer[index];index = (++index)%BufferSize;--numUsedBytes;mutex.unlock();bufferEmpty.wakeAll();}
}

四 调用

    Producer producer;Consumer consumer;Consumer consumerB;producer.start();consumer.start();consumerB.start();producer.wait();consumer.wait();consumerB.wait();

五 对qt书籍上示例的优化

5.1 wake的时机

  • 在这里我把wake的时机放到了解锁之后,也就是先解锁后wake
  • 虽然二者的顺序无关紧要,但是如果在这个场景下我们将wake放在解锁的后面,对于消费者而言,可能处理速度上就会快一点,因为很多情况下可能并没有在wait等待
  • 需要wakeall是立即激活所有等待的线程,此时会重新获得锁也就是lock(),但是也是会等待锁被释放后才能获取到。

5.2 消费者的线程同步问题

  • 我们需要在判断是否有可读的数据时也加上while循环判断来进行wait
  • 否则就会导致一种场景:当可用单元为0时,此时两个消费者都在wait,当生产者激活(将可以单元加1)后,比如消费者A先获取到锁,对其数据进行处理,此时就会导致一个问题,处理结束后可用单元numUsedByte变为了0,紧接着进行unlock解锁,但是此时消费者B就会紧接着获取到锁,因为它在上次numUsedByte等于0是也在等待获取锁。此时就会将这个numUsedByte变为-1,此时数据的处理就会乱套。

 

相关文章:

[qt] 线程等待与唤醒

对于生产者与消费者的数据处理的另一种好的解决方法是使用QWaitCondition类,允许线程在一定的条件下唤醒其他多个线程来共同处理。 一 定义公共变量 DataSize: 生产者生产数据的大小BufferSize: 也就是这个缓冲区的大小,每个单元是一个int&#xff0c;也有可能是一个链表,结构…...

Springboot 实现 Modbus Rtu 协议接入物联网设备

Modbus RTU 技术教程 引言 Modbus是一种开放标准的通信协议,它最初由Modicon(现施耐德电气)在1979年发布,旨在让可编程逻辑控制器(PLC)之间能够进行通信。随着时间的发展,Modbus已经成为工业自动化领域中最常用的通信协议之一,尤其适用于连接工业电子设备。本文将详细…...

鸿蒙笔记--装饰器

这一节主要了解一下鸿蒙里的装饰器,装饰器是一种特殊的语法结构&#xff0c;用于装饰类、结构体、方法以及变量; 1 Component在鸿蒙&#xff08;HarmonyOS&#xff09;开发中扮演着重要角色&#xff0c;主要用于定义可重用的UI组件,主要作用:1)组件化&#xff1a;Component装饰…...

不同环境下RabbitMQ的安装-3 操作RabbitMQ

前面两篇从不同环境下RabbitMQ的安装-1 为什么要使用消息服务 到同环境下RabbitMQ的安装-2 ARM架构、X86架构、Window系统环境下安装RabbitMQ介绍了关于如何在ARM架构、X86架构和Window系统下如何安装&#xff0c;各位小伙伴可以根据自己的实际开发场景参考安装。 到本篇是一些…...

postgregSQL配置vector插件

1.下载vector 下载vector&#xff1a;https://pgxn.org/dist/vector/0.5.1/ 放在&#xff1a;C:\Program Files\PostgreSQL\vector-0.5.1 2.安装Visual Studio 2022 下载&#xff1a;https://visualstudio.microsoft.com/zh-hans/downloads/ 安装Visual Studio是为了C编译环…...

PUMA论文阅读

PUMA: Efficient Continual Graph Learning with Graph Condensation PUMA&#xff1a;通过图压缩进行高效的连续图学习 ABSTRACT 在处理流图时&#xff0c;现有的图表示学习模型会遇到灾难性的遗忘问题&#xff0c;当使用新传入的图进行学习时&#xff0c;先前学习的这些模…...

算法学习day31(动态规划)

一、比特位计数 给你一个整数 n &#xff0c;对于 0 < i < n 中的每个 i &#xff0c;计算其二进制表示中 1 的个数 &#xff0c;返回一个长度为 n 1 的数组 ans 作为答案。 输入&#xff1a;n 2 输出&#xff1a;[0,1,1] 解释&#xff1a;0 --> 0 1 --> 1 2 -…...

嵌入式学Day25---Linux软件编程---线程间通信

目录 ​编辑 一、线程的分离属性 1.1.什么是分离属性 1.2.分离属性相关函数接口 1.初始化线程属性-pthread_attr_init() 2.销毁线程属性-pthread_attr_destory() 3.设置线程属性-pthread_setdetachstate() 1.3.注意 二、互斥锁 2.1.资源 2.2.互斥锁 1.什么是互斥锁 2.互…...

【实现100个unity特效之17】在unity中使用shader和ShaderGraph分别实现模糊特定层,高斯模糊效果

最终效果 Unity通过Shader来模糊场景画面 参考&#xff1a;【游戏开发小技】Unity通过UI全屏图来模糊场景画面&#xff08;Shader | 模糊 | 滤镜 | Blur&#xff09; ShaderGraph实现图片的高斯模糊 参考&#xff1a;【游戏开发实战】Unity ShaderGraph实现图片的高斯模糊效…...

Unity补完计划 之 SpriteEditer Multiple

本文仅作笔记学习和分享&#xff0c;不用做任何商业用途 本文包括但不限于unity官方手册&#xff0c;unity唐老狮等教程知识&#xff0c;如有不足还请斧正 1. SpriteEditer Multiple Automatic slicing - Unity 手册 这是用于裁剪图集的模式 应用之后精灵编辑器会看到Slice亮…...

C++ IOStream

IOStream 类流特性 不可赋值和复制缓冲重载了<< >> 状态位 示例 状态位操作函数coutcin getget(s,n)/get(s,n,d):getline otherif(!fs)/while(cin) operator void*()与 operator!()代码示例 File Stream open 函数 文件打开方式 文件读写 读写接口 一次读一个字符…...

2024/8/8训练

A - 无线网络整点栅格统计 题目链接 算法:模拟 题目大意 给你一个n*m的网格,然后输出每一个点作为顶点能构成的正方形数量(可以为斜正方形). 算法思路 本身题目数据是很小的,可以通过n^2的时间复杂度枚举每一个顶点,然后再通过n平方的时间复杂度枚举出另一个对角顶点,判断…...

项目的小结

项目场景&#xff1a; 作业的发布&#xff0c;打回 。 学生端做作业 由作业的state来确定作业是否上交&#xff0c;批改&#xff0c;打回作业。 实体类的建立&#xff0c;还有各种成员变量的设计要满足需求 问题描述 问题&#xff1a; 在进行上传作业后&#xff0c;老师端…...

【目标检测实验系列】YOLOv5高效涨点:基于NAMAttention规范化注意力模块,调整权重因子关注有效特征(文内附源码)

1. 文章主要内容 本篇博客主要涉及规范化注意力机制&#xff0c;融合到YOLOv5(v6.1版本&#xff0c;去掉了Focus模块)模型中&#xff0c;通过惩罚机制&#xff0c;调整特征权重因子&#xff0c;使模型更加关注有效特征&#xff0c;助力模型涨点。 2. 简要概括 论文地址&#x…...

LSPatch制作内置模块应用软件无需root 教你制作内置应用

前言 LSPatch功能非常强大&#xff0c;它是一款基于LSPosed核心的免Root Xposed框架软件。这意味着用户无需进行手机root操作&#xff0c;即可轻松植入内置Xposed模块&#xff0c;享受更多定制化的功能和体验&#xff0c;比如微某内置模块版等&#xff0c;这为那些不想root手机…...

Java设计模式七大原则

本篇为七大原则概述&#xff0c;后面会有每个原则的介绍&#xff0c;喜欢的朋友可以蹲一下哦&#xff01;&#xff01;&#xff01;&#xff01; Java设计模式的七大原则一般是指“面向对象设计原则”&#xff0c;这些原则有助于在设计软件系统时提高代码的可维护性、可扩展性和…...

Copy as cURL 字段含义

当前端在开发过程中&#xff0c;遇到接口错误反馈给后端人员时&#xff0c;一般在此接口处右键复制为cURL。 格式如下&#xff1a; curl https://xxx.xxx.cn/xxx/xxx/management/record/list \-H accept: application/json, text/plain, */* \-H accept-language: zh-CN,zh;q0…...

mysql更改密码后,若依 后端启动不了解决方案

我原先的mysql 密码是 数字字符串 我想改成000 纯数字 改完之后&#xff0c;连接的数据库的代码 也更改后 &#xff0c;后端启动不了 因为原先 密码数字字符串 不需要用引号" " 括起来 我改成纯数字 需要用 " " 括起来 如下图 然后就可以运行成功了...

Redis--缓存击穿、缓存穿透、缓存雪崩

缓存击穿 什么是缓存击穿呢&#xff1f; 在高并发的场景下,一个热点的缓存数据在redis中突然失效(过期或被删除时&#xff0c;所有的读请求都会直接落在数据库上&#xff0c;导致数据库瞬间压力剧增&#xff0c;严重时可能会造成数据库宕机。这种情况就是所谓的“缓存击穿”。(…...

10个理由告诉你,为什么鸿蒙是下一个职业风口!

在当今科技飞速发展的时代&#xff0c;新的技术和趋势不断涌现&#xff0c;为人们带来了前所未有的机遇和挑战。鸿蒙操作系统作为我国自主研发的创新成果&#xff0c;正逐渐成为科技领域的焦点&#xff0c;被认为是下一个职业风口。 10个理由告诉你&#xff0c;为什么鸿蒙是下一…...

Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例

使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件&#xff0c;常用于在两个集合之间进行数据转移&#xff0c;如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model&#xff1a;绑定右侧列表的值&…...

iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版​分享

平时用 iPhone 的时候&#xff0c;难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵&#xff0c;或者买了二手 iPhone 却被原来的 iCloud 账号锁住&#xff0c;这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...

为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?

在建筑行业&#xff0c;项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升&#xff0c;传统的管理模式已经难以满足现代工程的需求。过去&#xff0c;许多企业依赖手工记录、口头沟通和分散的信息管理&#xff0c;导致效率低下、成本失控、风险频发。例如&#…...

ffmpeg(四):滤镜命令

FFmpeg 的滤镜命令是用于音视频处理中的强大工具&#xff0c;可以完成剪裁、缩放、加水印、调色、合成、旋转、模糊、叠加字幕等复杂的操作。其核心语法格式一般如下&#xff1a; ffmpeg -i input.mp4 -vf "滤镜参数" output.mp4或者带音频滤镜&#xff1a; ffmpeg…...

网站指纹识别

网站指纹识别 网站的最基本组成&#xff1a;服务器&#xff08;操作系统&#xff09;、中间件&#xff08;web容器&#xff09;、脚本语言、数据厍 为什么要了解这些&#xff1f;举个例子&#xff1a;发现了一个文件读取漏洞&#xff0c;我们需要读/etc/passwd&#xff0c;如…...

【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的“no matching...“系列算法协商失败问题

【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的"no matching..."系列算法协商失败问题 摘要&#xff1a; 近期&#xff0c;在使用较新版本的OpenSSH客户端连接老旧SSH服务器时&#xff0c;会遇到 "no matching key exchange method found"​, "n…...

轻量级Docker管理工具Docker Switchboard

简介 什么是 Docker Switchboard &#xff1f; Docker Switchboard 是一个轻量级的 Web 应用程序&#xff0c;用于管理 Docker 容器。它提供了一个干净、用户友好的界面来启动、停止和监控主机上运行的容器&#xff0c;使其成为本地开发、家庭实验室或小型服务器设置的理想选择…...

Java中HashMap底层原理深度解析:从数据结构到红黑树优化

一、HashMap概述与核心特性 HashMap作为Java集合框架中最常用的数据结构之一&#xff0c;是基于哈希表的Map接口非同步实现。它允许使用null键和null值&#xff08;但只能有一个null键&#xff09;&#xff0c;并且不保证映射顺序的恒久不变。与Hashtable相比&#xff0c;Hash…...

统计学(第8版)——统计抽样学习笔记(考试用)

一、统计抽样的核心内容与问题 研究内容 从总体中科学抽取样本的方法利用样本数据推断总体特征&#xff08;均值、比率、总量&#xff09;控制抽样误差与非抽样误差 解决的核心问题 在成本约束下&#xff0c;用少量样本准确推断总体特征量化估计结果的可靠性&#xff08;置…...

IP选择注意事项

IP选择注意事项 MTP、FTP、EFUSE、EMEMORY选择时&#xff0c;需要考虑以下参数&#xff0c;然后确定后选择IP。 容量工作电压范围温度范围擦除、烧写速度/耗时读取所有bit的时间待机功耗擦写、烧写功耗面积所需要的mask layer...