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

Qt (19)【Qt 线程安全 | 互斥锁QMutex QMutexLocker | 条件变量 | 信号量】

阅读导航

  • 引言
  • 一、互斥锁
    • 1. QMutex
      • (1)基本概念
      • (2)使用示例
        • 基本需求
        • ⭕thread.h
        • ⭕thread.cpp
        • ⭕widget.h
        • ⭕widget.cpp
    • 2. QMutexLocker
      • (1)基本概念
      • (2)使用示例
    • 3. QReadWriteLocker、QReadLocker、QWriteLocker
      • (1)基本概念
      • (2)使用示例
  • 二、条件变量
    • 1. 基本概念
    • 2. 使用示例
  • 三、信号量
    • 1. 基本概念
    • 2. 使用示例

引言

在Qt中,为了构建高效且安全的多线程应用程序,我们需要关注线程安全问题。Qt提供了几种关键的同步机制,包括互斥锁(QMutex)及其自动管理助手QMutexLocker,用于确保资源互斥访问;条件变量,用于线程间的协调与等待/唤醒机制;以及信号量,用于控制对资源的并发访问数。这些工具共同协作,帮助开发者避免数据竞争和死锁,实现线程间的安全交互。
(PS:Linux有详细讲过这方面的知识,传送门:💻【探索Linux】P.21多线程 | 线程同步 | 条件变量 | 线程安全)

一、互斥锁

互斥锁是⼀种保护和防止多个线程同时访问同⼀对象实例的方法,在Qt中,互斥锁主要是通过QMutex类来处理

1. QMutex

(1)基本概念

QMutex 是 Qt 框架中一个重要的类,它实现了互斥锁的功能。主要用途是在多线程程序中保护对共享资源的访问,通过锁定和解锁机制来确保同一时间只有一个线程能够访问特定的数据或执行某段代码,从而避免数据竞争和不一致的问题,实现线程间的互斥操作,保证程序的线程安全性

(2)使用示例

基本需求

使用两个线程对同一个全局变量进行加加,每个线程加5000次

⭕thread.h
#ifndef THREAD_H
#define THREAD_H#include <QWidget>
#include <QThread>
#include <QMutex>class Thread : public QThread
{Q_OBJECT
public:Thread();// 添加一个 static 成员.static int num;// 创建锁对象static QMutex mutex;void run();
};#endif // THREAD_H
⭕thread.cpp
#include "thread.h"
#include <QMutexLocker>int Thread::num = 0;QMutex Thread::mutex;Thread::Thread()
{
}void Thread::run()
{for (int i = 0; i < 50000; i++) {mutex.lock();num++;mutex.unlock();}
}
⭕widget.h
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();private:Ui::Widget *ui;
};
#endif // WIDGET_H
⭕widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include "thread.h"
#include <QDebug>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);// 创建两个线程对象.Thread t1;Thread t2;t1.start();t2.start();// 加上线程的等待, 让主线程等待这俩线程执行结束.t1.wait();t2.wait();// 打印结果.qDebug() << Thread::num;
}Widget::~Widget()
{delete ui;
}

2. QMutexLocker

(1)基本概念

QMutexLockerQMutex 的一个辅助类,它采用了资源获取即初始化(RAII, Resource Acquisition Is Initialization)的设计模式。这一模式确保了互斥锁(QMutex)在 QMutexLocker 对象的生命周期内被自动上锁,并在该对象被销毁时自动解锁。通过这种方式,QMutexLocker 极大地简化了对互斥锁的管理,开发者无需手动调用上锁(lock)和解锁(unlock)函数,从而避免了因忘记解锁而导致的死锁等潜在问题。

(2)使用示例

在这里插入图片描述
上面的QMutex的示例代码只用进行图片中的变换就可以使用QMutexLocker了。

3. QReadWriteLocker、QReadLocker、QWriteLocker

(1)基本概念

QReadWriteLock 是一个读写锁类,它设计用于精细控制对共享资源的并发访问权限,特别是在处理读写操作时。在这个锁机制中,区分了读操作和写操作的不同需求。

  • QReadLocker 是用于读操作的上锁工具。当多个线程需要同时读取共享资源时,QReadLocker 允许这些线程同时获得读锁,从而并行访问资源。这种方式提高了读取操作的并发效率,因为读取通常不会修改数据,因此多个读者可以同时安全地访问资源。

  • QWriteLocker 则是用于写操作的上锁工具。与读操作不同,写操作会修改共享资源,因此 QWriteLocker 确保在任何给定时间内,只有一个线程能够持有写锁,从而独占对共享资源的写入权限。这保证了数据的一致性和完整性,避免了并发写入可能导致的冲突。

(2)使用示例

	QReadWriteLock rwLock;//在读操作中使⽤读锁{QReadLocker locker(&rwLock); //在作⽤域内⾃动上读锁//读取共享资源//...} //在作⽤域结束时⾃动解读锁//在写操作中使⽤写锁{QWriteLocker locker(&rwLock); //在作⽤域内⾃动上写锁//修改共享资源//...} //在作⽤域结束时⾃动解写锁

二、条件变量

1. 基本概念

在多线程编程中,有时线程需要等待某个条件成立才能继续执行。Qt提供了QWaitCondition类来处理这种情况。QWaitCondition允许线程在条件不满足时暂停(等待),并在条件满足时被其他线程唤醒。这样,线程可以基于条件进行同步和协调,而不仅仅是简单地轮流使用资源。

2. 使用示例

QMutex mutex;
QWaitCondition condition;//在等待线程中
mutex.lock();//检查条件是否满⾜,若不满⾜则等待while (!conditionFullfilled())
{condition.wait(&mutex); //等待条件满⾜并释放锁
}//条件满⾜后继续执⾏
//...mutex.unlock();//在改变条件的线程中
mutex.lock();//改变条件
changeCondition();
condition.wakeAll(); //唤醒等待的线程mutex.unlock();

三、信号量

1. 基本概念

在多线程编程中,如果多个线程需要访问有限的资源(如内存),就需要控制同时访问这些资源的线程数量。Qt中的QSemaphore就是一个工具,它可以限制同时运行的线程数,从而管理资源的使用。简单来说,QSemaphore就像一个计数器,用于确保不会有太多线程同时占用资源。

2. 使用示例

QSemaphore semaphore(2); //同时允许两个线程访问共享资源//在需要访问共享资源的线程中
semaphore.acquire(); //尝试获取信号量,若已满则阻塞//访问共享资源
//...semaphore.release(); //释放信号量//在另⼀个线程中进⾏类似操作

相关文章:

Qt (19)【Qt 线程安全 | 互斥锁QMutex QMutexLocker | 条件变量 | 信号量】

阅读导航 引言一、互斥锁1. QMutex&#xff08;1&#xff09;基本概念&#xff08;2&#xff09;使用示例基本需求⭕thread.h⭕thread.cpp⭕widget.h⭕widget.cpp 2. QMutexLocker&#xff08;1&#xff09;基本概念&#xff08;2&#xff09;使用示例 3. QReadWriteLocker、QR…...

Java语法-类和对象(上)

1. 面向对象的初步认识 1.1 什么是面向对象 概念: Java是一门纯面向对象的语言(Object Oriented Program&#xff0c;简称OOP)&#xff0c;在面向对象的世界里&#xff0c;一切皆为对象。 1.2 面向对象VS面向过程 如:洗衣服 面向过程: 注重的是洗衣服的过程,少了一个环节也不…...

Presto如何配置资源队列或资源组

Presto的任务队列配置主要涉及到查询队列和资源组的配置&#xff0c;这些配置通常用于管理Presto集群中的查询执行和资源分配。但是注意这两个东西是共存&#xff0c;互补的关系&#xff0c;并不需要纠结那种配置方式更加出色 一、查询队列配置 Presto的查询队列配置主要通过…...

828华为云征文|使用Flexus X实例集成ES搜索引擎

目录 一、应用场景 1.1 Flexus X实例概述 1.2 ES搜索引擎 二、安装相关服务 2.1 安装Elasticsearch7.17.0 2.2 安装kibana7.17.0 三、开通安全组规则 四、整体感受 4.1 Flexus X实例 4.2 使用感觉 一、应用场景 1.1 Flexus X实例概述 Flexus X实例是华为云推出的一款…...

【设计模式-访问者模式】

定义 访问者模式&#xff08;Visitor Pattern&#xff09;是一种行为型设计模式&#xff0c;允许你在不修改已有类的情况下向这些类添加新的功能或行为。它通过将操作的执行逻辑从对象的类中分离出来&#xff0c;使得你可以在保持类的封闭性&#xff08;符合开闭原则&#xff…...

一元运算符(自增自减)

一、一元运算符 一元运算符&#xff0c;只需要一个操作数 1. 正号 正号不会对数字产生任何影响 2.-负号 负号可以对数字进行负号的取反 对于非Number的值&#xff0c;会将先转换为Number&#xff0c;在进行运算: 可以对一个其他的数据类型使用&#xff0c;来将其转换为n…...

gitlab/极狐-离线包下载地址

如果想要使用Gitlab/极狐进行数据的恢复&#xff0c;只能使用相同版本或者相近版本的安装包&#xff0c;因此有时候需要到它的官网上下载对应版本的安装包&#xff0c;以下是我收集到的对应地址的下载路径&#xff1a; Gitlab Gitlab离线库&#xff0c; https://packages.gitl…...

C++——输入三个整数,按照由小到大的顺序输出。用指针方法处理。

没注释的源代码 #include <iostream> using namespace std; void swap(int *m,int *n); int main() { int a,b,c; int *p1,*p2,*p3; cout<<"请输入三个整数&#xff1a;"<<endl; cin>>a>>b>>c; p1&a;p2&b;p3&c;…...

【Java8 重要特性】Lambda 表达式

文章目录 Lambda函数式接口Lambda 规则规范简化过程改写 Arrays.setAll()改写 Arrays.sort() forEach循环 list 集合循环 list 集合并输出对象信息循环 Map 集合 方法引用和构造器引用方法引用构造器引用 Lambda Lambda是一个匿名函数&#xff0c;我们可以将Lambda表达式理解为…...

word2vec--CBOW与Skip-Gram 两种模型

Word2Vec 是一种流行的用于生成词嵌入&#xff08;Word Embeddings&#xff09;的无监督学习模型&#xff0c;它由 Google 的一个团队在 2013 年提出。它的主要目的是将单词映射到一个连续的向量空间&#xff0c;使得语义相似的单词在这个空间中靠得更近。 Word2Vec 有两种主要…...

iOS六大设计原则设计模式

六大设计原则&#xff1a; 一、单一职责原则 一个类或者模块只负责完成一个职责或者功能。 类似于&#xff1a;UIView 和 CALayer 二、开放封闭原则 对扩展开放&#xff0c;对修改封闭。 我们要尽量通过扩展软件实体来解决需求变化&#xff0c;而不是通过修改已有的代码来…...

nacos 集群搭建

主机准备 IProle192.168.142.155slave02192.168.142.156slave192.168.142.157master 三台主机上分别构建 mysql 镜像 FROM mysql:8.0.31 ADD https://raw.githubusercontent.com/alibaba/nacos/develop/distribution/conf/mysql-schema.sql /docker-entrypoint-initdb.d/nac…...

STM32快速复习(十二)FLASH闪存的读写

文章目录 一、FLASH是什么&#xff1f;FLASH的结构&#xff1f;二、使用步骤1.标准库函数2.示例函数 总结 一、FLASH是什么&#xff1f;FLASH的结构&#xff1f; 1、FLASH简介 &#xff08;1&#xff09;STM32F1系列的FLASH包含程序存储器、系统存储器和选项字节三个部分&…...

漏洞扫描工具使用

首先把补丁的两个文件复制下来替换原文件 找到C:\ProgramData\Acunetix\shared\license然后替换 然后打开漏扫工具并刷新页面 然后添加要扫描的网站 等他扫描完成 扫描完成就可以生成报告了 一共五十多页的报告...

C++ | Leetcode C++题解之第424题替换后的最长重复字符

题目&#xff1a; 题解&#xff1a; class Solution { public:int characterReplacement(string s, int k) {vector<int> num(26);int n s.length();int maxn 0;int left 0, right 0;while (right < n) {num[s[right] - A];maxn max(maxn, num[s[right] - A]);i…...

利士策分享,动摇时刻的自我救赎

利士策分享&#xff0c;动摇时刻的自我救赎 在人生的长河中&#xff0c;我们每个人都会面临各种挑战与抉择&#xff0c; 那些让人心生动摇的瞬间&#xff0c;如同夜空中偶尔掠过的乌云&#xff0c;遮蔽了前行的星光。 但正是这些动摇&#xff0c;构成了我们成长的轨迹&#x…...

动手学深度学习(李沐)PyTorch 第 1 章 引言

在线电子书 深度学习介绍 安装 使用conda环境 conda create -n d2l-zh python3.8 pip安装需要的包 pip install jupyter d2l torch torchvision下载代码并执行 wget https://zh-v2.d2l.ai/d2l-zh.zip unzip d2l-zh.zip jupyter notebookpip install rise如果不想使用jupyt…...

二叉树(二)深度遍历和广度遍历

一、层序遍历 广度优先搜索&#xff1a;使用队列&#xff0c;先进先出 模板&#xff1a; 1、定义返回的result和用于辅助的队列 2、队列初始化&#xff1a; root非空时进队 3、遍历整个队列&#xff1a;大循环while(!que.empty()) 记录每层的size以及装每层结果的变量&a…...

【算法——双指针】

922. 按奇偶排序数组 II 算法讲解050【必备】双指针技巧与相关题目_哔哩哔哩_bilibili main:vector<int>nums { 3,1,2,4 };int i 0, j 1;int n nums.size() - 1;while (j < nums.size() && i < nums.size()) //如果奇偶任一方排好了&#xff0c;另…...

Rocky Linux 9 中添加或删除某个网卡的静态路由的方法

使用ip命令配置临时路由 添加静态路由 ip route add <目的网络> via <下一跳IP> dev <网卡接口名称>例: 给eth0网卡添加一个到达 192.168.2.0/24 网络&#xff0c;下一跳为 192.168.1.254 的路由 ip route add 192.168.2.0/24 via 192.168.1.254 dev eth0…...

Cursor实现用excel数据填充word模版的方法

cursor主页&#xff1a;https://www.cursor.com/ 任务目标&#xff1a;把excel格式的数据里的单元格&#xff0c;按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例&#xff0c;…...

Java 语言特性(面试系列1)

一、面向对象编程 1. 封装&#xff08;Encapsulation&#xff09; 定义&#xff1a;将数据&#xff08;属性&#xff09;和操作数据的方法绑定在一起&#xff0c;通过访问控制符&#xff08;private、protected、public&#xff09;隐藏内部实现细节。示例&#xff1a; public …...

【OSG学习笔记】Day 18: 碰撞检测与物理交互

物理引擎&#xff08;Physics Engine&#xff09; 物理引擎 是一种通过计算机模拟物理规律&#xff08;如力学、碰撞、重力、流体动力学等&#xff09;的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互&#xff0c;广泛应用于 游戏开发、动画制作、虚…...

Psychopy音频的使用

Psychopy音频的使用 本文主要解决以下问题&#xff1a; 指定音频引擎与设备&#xff1b;播放音频文件 本文所使用的环境&#xff1a; Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...

JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作

一、上下文切换 即使单核CPU也可以进行多线程执行代码&#xff0c;CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短&#xff0c;所以CPU会不断地切换线程执行&#xff0c;从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...

听写流程自动化实践,轻量级教育辅助

随着智能教育工具的发展&#xff0c;越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式&#xff0c;也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建&#xff0c;…...

BLEU评分:机器翻译质量评估的黄金标准

BLEU评分&#xff1a;机器翻译质量评估的黄金标准 1. 引言 在自然语言处理(NLP)领域&#xff0c;衡量一个机器翻译模型的性能至关重要。BLEU (Bilingual Evaluation Understudy) 作为一种自动化评估指标&#xff0c;自2002年由IBM的Kishore Papineni等人提出以来&#xff0c;…...

OD 算法题 B卷【正整数到Excel编号之间的转换】

文章目录 正整数到Excel编号之间的转换 正整数到Excel编号之间的转换 excel的列编号是这样的&#xff1a;a b c … z aa ab ac… az ba bb bc…yz za zb zc …zz aaa aab aac…; 分别代表以下的编号1 2 3 … 26 27 28 29… 52 53 54 55… 676 677 678 679 … 702 703 704 705;…...

二维FDTD算法仿真

二维FDTD算法仿真&#xff0c;并带完全匹配层&#xff0c;输入波形为高斯波、平面波 FDTD_二维/FDTD.zip , 6075 FDTD_二维/FDTD_31.m , 1029 FDTD_二维/FDTD_32.m , 2806 FDTD_二维/FDTD_33.m , 3782 FDTD_二维/FDTD_34.m , 4182 FDTD_二维/FDTD_35.m , 4793...

GAN模式奔溃的探讨论文综述(一)

简介 简介:今天带来一篇关于GAN的,对于模式奔溃的一个探讨的一个问题,帮助大家更好的解决训练中遇到的一个难题。 论文题目:An in-depth review and analysis of mode collapse in GAN 期刊:Machine Learning 链接:...