【QT5 多线程示例】互斥锁

互斥锁

互斥锁介绍:【C++并发编程】(三)互斥锁:std::mutex。原理都一样,这里就不赘述了。

QMutex 是 Qt 框架中提供的一个互斥锁类,主要包括以下成员函数:

  • lock():试图锁定互斥量。如果另一个线程已经锁定了这个互斥量,调用线程将被阻塞,直到那个线程解锁。
  • unlock():解锁互斥量,允许其他线程锁定它。
  • tryLock():尝试锁定互斥量,不阻塞调用线程。如果互斥量被锁定,函数返回 false;如果成功锁定,返回 true
  • tryLock(int timeout):尝试在指定的毫秒数内锁定互斥量。如果超时仍未锁定,返回 false;如果成功锁定,返回 true
  • locked():查询互斥量当前是否被锁定。如果被锁定,返回 true;否则返回 false

在简单的函数中,可以直接使用 QMutex 的 lock()unlock() 成员函数。但在复杂的函数中,使用 QMutexLocker 自动管理互斥锁更为安全和方便。QMutexLocker 与C++标准中std::lock_guard的用法差不多,而且也是基于 RAII(Resource Acquisition Is Initialization)机制的,在构造时自动锁定互斥量,在析构时自动解锁。

下面给出示例代码:
https://github.com/BinaryAI-1024/QtStudy/tree/master/thread/mutex

//myworker.h
#ifndef MYWORKER_H
#define MYWORKER_H#include <QObject>
#include <QMutex>
#include <QDebug>class MyWorker : public QObject
{Q_OBJECT
signals:void finished();public:explicit MyWorker(QObject *parent = nullptr);// 获取 counter 的值static int getCounter();public slots:void doWork(int id);private:static QMutex mutex;static int counter;
};#endif // MYWORKER_H
//myworker.cpp
#include "myworker.h"// 静态成员初始化
QMutex MyWorker::mutex;
int MyWorker::counter = 0;MyWorker::MyWorker(QObject *parent): QObject(parent)
{
}void MyWorker::doWork(int id)
{qDebug() << "Worker" << id << "started work.";for (int i = 0; i < 100000; ++i) {QMutexLocker locker(&mutex); // // 加锁以保护数据++counter;}emit finished(); // 发送完成信号
}int MyWorker::getCounter()
{return counter;
}
//main.cpp
#include <QCoreApplication>
#include <QThread>
#include "myworker.h"
#include <QTimer>
#include <QMutex>
#include <QMutexLocker>int main(int argc, char *argv[])
{QCoreApplication app(argc, argv);QMutex mutex;                  // 创建一个互斥锁const int numThreads = 3;      // 定义要启动的线程数量QThread *threads[numThreads];  // 创建一个 QThread 指针数组,用于存储线程对象MyWorker *workers[numThreads]; // 创建一个 MyWorker 指针数组,用于存储工作对象int finishedCount = 0;         // 初始化一个计数器,用于跟踪完成的线程数量// 循环创建和启动线程for (int i = 0; i < numThreads; ++i) {threads[i] = new QThread; // 创建一个新线程workers[i] = new MyWorker; // 创建一个新工作对象workers[i]->moveToThread(threads[i]); // 将工作对象移动到新线程中// 连接线程的 started 信号到工作对象的 doWork 槽,使用 QTimer 确保在事件循环开始后执行QObject::connect(threads[i], &QThread::started, workers[i], [=]() {QTimer::singleShot(0, workers[i], [=]() { workers[i]->doWork(i); });});// 连接工作对象的 finished 信号到线程的 quit 槽,以便任务完成后退出线程的事件循环QObject::connect(workers[i], &MyWorker::finished, threads[i], &QThread::quit);// 连接工作对象的 finished 信号到工作对象的 deleteLater 槽,以便任务完成后删除工作对象QObject::connect(workers[i], &MyWorker::finished, workers[i], &QObject::deleteLater);// 连接线程的 finished 信号到线程的 deleteLater 槽,以便线程退出后删除线程对象QObject::connect(threads[i], &QThread::finished, threads[i], &QObject::deleteLater);// 连接工作对象的 finished 信号到一个 lambda 表达式,用于更新计数器并检查所有线程是否完成QObject::connect(workers[i], &MyWorker::finished, [&finishedCount, &mutex, i]() {QMutexLocker locker(&mutex); // 加锁以保护计数器的访问++finishedCount; // 增加已完成线程的计数qDebug() << "Worker" << i << "finished. " ;if (finishedCount == numThreads) { // 检查是否所有线程都已完成// 每个线程使counter增加100000,正确结果应该是:numThreads*100000qDebug() << "counter:" << MyWorker::getCounter();}});threads[i]->start(); // 启动线程}return app.exec();
}

结果:

Worker 1 started work.
Worker 0 started work.
Worker 2 started work.
Worker 1 finished. 
Worker 2 finished. 
Worker 0 finished. 
counter: 300000

互斥锁在代码中保护了main.cpp中的 ++finishedCount;以及mythread.cpp中的++counter;,避免了多个线程同时执行这些操作导致的错误。QMutexLocker能够自动管理局部作用域内互斥锁的加锁和开锁。

另外,在这段代码中,不需要调用 thread.wait() 是因为 Qt 的信号和槽机制自动管理了线程的生命周期。通过 QThread::quit()QObject::deleteLater(),线程在任务完成后自动退出并清理资源。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/37020.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于Rockylinux9.5(LTS-SP4)安装MySQL Community Server 9.2.0

目录 一、安装环境及准备 1、linux操作系统环境 2、MYSQL安装包准备 二、执行安装 1、解压软件包 2、按顺序执行软件包的安装 3、启动MYSQL服务 4.配置MYSQL 一、安装环境及准备 1、linux操作系统环境 Rocky linux9.5安装在VMware虚拟机上完成Rocky linux9.5安装&am…

分布式任务调度

今天我们讲讲分布式定时任务调度—ElasticJob。 一、概述 1、什么是分布式任务调度 我们可以思考⼀下下⾯业务场景的解决⽅案: 某电商平台需要每天上午10点&#xff0c;下午3点&#xff0c;晚上8点发放⼀批优惠券 某银⾏系统需要在信⽤卡到期还款⽇的前三天进⾏短信提醒 某…

Blender标注工具

按住键盘D键 鼠标左键绘制 / 右键擦除 也可以在上方选择删除

Second Me:在 AI 中保留自我的火种丨社区来稿

今天想和所有朋友们分享一种全新的 AI 可能性&#xff0c;Second Me&#xff01; 2025年了&#xff0c;很多人和我一样&#xff0c;都越来越确信&#xff0c;AGI 的到来只是一个时间问题。 然而我也经常想&#xff0c;当我们所有人&#xff0c;都心甘情愿地为自己“造神” –…

仿新浪微博typecho主题源码

源码介绍 仿新浪微博typecho主题源码&#xff0c;简约美观&#xff0c;适合做个人博客&#xff0c;该源码为主题模板&#xff0c;需要先搭建typecho&#xff0c;然后吧源码放到对应的模板目录下&#xff0c;后台启用即可 源码特点 支持自适应 个性化程度高 可设置背景图、顶…

Ubuntu24搭建k8s高可用集群

Ubuntu24搭建k8s高可用集群 环境信息 主机名IPk8s版本备注vm-master192.168.103.2501.28.2master1vm-master2192.168.103.2491.28.2master2vm-master3192.168.103.2541.28.2master3vm-node1192.168.103.2511.28.2node1vm-node2192.168.103.2521.28.2node2 容器进行时&#xf…

洛谷P1216 [IOI 1994] 数字三角形 Number Triangles(动态规划)

P1216 [IOI 1994] 数字三角形 Number Triangles - 洛谷 代码区&#xff1a; #include<algorithm> #include<iostream>using namespace std; const int R 1005; int dp[R][R]; int arr[R][R]; int main() {int n;cin >> n;for (int i 1; i < n; i) {for…

Spring Boot Actuator 自定义健康检查(附Demo)

目录 前言1. Demo2. 拓展 前言 &#x1f91f; 找工作&#xff0c;来万码优才&#xff1a;&#x1f449; #小程序://万码优才/r6rqmzDaXpYkJZF Spring Boot 的 actuator 提供了应用监控的功能&#xff0c;其中健康检查&#xff08;Health Check&#xff09;是一个重要的部分&…

2025年优化算法:人工旅鼠算法(Artificial lemming algorithm,ALA)

人工旅鼠算法(Artificial lemming algorithm&#xff0c;ALA)是发表在中科院二区期刊“ARTIFICIAL INTELLIGENCE REVIEW”&#xff08;IF&#xff1a;11.7&#xff09;的2025年智能优化算法 01.引言 随着信息技术与工程科学的快速发展&#xff0c;现代优化问题呈现出高维、非线…

「实战指南 」Swift 并发中的任务取消机制

网罗开发 &#xff08;小红书、快手、视频号同名&#xff09; 大家好&#xff0c;我是 展菲&#xff0c;目前在上市企业从事人工智能项目研发管理工作&#xff0c;平时热衷于分享各种编程领域的软硬技能知识以及前沿技术&#xff0c;包括iOS、前端、Harmony OS、Java、Python等…

实验12深度学习

实验12深度学习 一、实验目的 &#xff08;1&#xff09;理解并熟悉深度神经网络的工作原理&#xff1b; &#xff08;2&#xff09;熟悉常用的深度神经网络模型及其应用环境&#xff1b; &#xff08;3&#xff09;掌握Anaconda的安装和设置方法&#xff0c;进一步熟悉Jupyte…

【问题解决】Postman 测试报错 406

现象 Tomcat 日志 org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver.logException Resolved org.springframework.web.HttpMediaTypeNotAcceptableException: No acceptable representation HTTP状态 406 - 不可接收 的报错&#xff0c;核心原因 客…

微信小程序:用户拒绝小程序获取当前位置后的处理办法

【1】问题描述&#xff1a; 小程序在调用 wx.getLocation() 获取用地理位置时&#xff0c;如果用户选择拒绝授权&#xff0c;代码会直接抛出错误。如果再次调用 wx.getLocation() 时&#xff0c;就不会在弹窗询问用户是否允许授权。导致用户想要重新允许获取地理位置时&#x…

【MySQL】内置函数

目录 一、日期时间函数1.1 简单使用1.2 案例实操 二、字符串函数2.1 简单使用2.2 案例实践2.2.1 获取emp表的ename列的字符集2.2.2 要求显示exam_result表中的信息&#xff0c;显示格式&#xff1a;“XXX的语文是XXX分&#xff0c;数学XXX分&#xff0c;英语XXX分”2.2.3 求exa…

模块二 单元4 安装AD+DC

模块二 单元4 安装ADDC 两个任务&#xff1a; 1.安装AD活动目录 2.升级当前服务器为DC域控制器 安装前的准备工作&#xff1a; 确定你要操作的服务器系统&#xff08;Windows server 2022&#xff09;&#xff1b; 之前的服务器系统默认是工作组的模式workgroup模式&#xff08…

卫星互联网智慧杆:开启智能城市新时代​

哇哦&#xff01;在当下这个数字化浪潮正以雷霆万钧之势席卷全球的超酷时代&#xff0c;智慧城市建设已然成为世界各国你追我赶、竞相发力的核心重点领域啦&#xff01;而咱们的卫星互联网智慧杆&#xff0c;作为一项完美融合了卫星通信与物联网顶尖技术的创新结晶&#xff0c;…

ThreadLocal 的详细使用指南

一、ThreadLocal 核心原理 ThreadLocal 是 Java 提供的线程绑定机制&#xff0c;为每个线程维护变量的独立副本。其内部通过 ThreadLocalMap 实现&#xff0c;每个线程的 Thread 对象都有一个独立的 ThreadLocalMap&#xff0c;存储以 ThreadLocal 对象为键、线程局部变量为值…

免费开源的NAS解决方案:TrueNAS

TrueNAS是业内知名的FreeNAS系统的升级版&#xff0c;是一款开源的网络存储系统&#xff0c;具有高性能、稳定性和易用性等优点。 TrueNAS目前有三个版本&#xff0c;分别是TrueNAS CORE、TrueNAS ENTERPRISE、TrueNAS SCALE。其中&#xff0c;TrueNAS CORE基于FreeBSD开发&…

Fisher 信息矩阵公式原理:使用似然估计,二阶导数等知识点

Fisher 信息矩阵公式原理:使用似然估计,二阶导数等知识点 目录 Fisher 信息矩阵公式原理:使用似然估计,二阶导数等知识点Fisher 通过似然估计求解真实数据和权重参数之间的差异**1. Fisher 信息矩阵的定义****2. 计算对数似然函数的二阶导数****3. 代入 Fisher 信息矩阵定义…

自定义myshell(精讲)

我们都知道&#xff0c;我们给Linux下发的指令都是shell帮我们处理并完成的&#xff0c;那么他是怎么完成的呢&#xff1f;不难想到他都是通过环境变量以及程序替换来完成的。我们这一篇文章就手把手来教你怎么自己实现一个简单的shell。 目标&#xff1a; 1.要能处理普通命令 …