Qt——多线程

一、QThread类

        如果要设计多线程程序,一般是从QThread继承定义一个线程类,并重新定义QThread的虚函数 run() ,在函数 run() 里处理线程的事件循环。

        应用程序的线程称为主线程,创建的其他线程称为工作线程。主线程的 start() 函数会在其内部调用 run() 函数,然后 exec() 函数会让 run() 函数保持运行,进入工作线程的事件循环,随时接收系统事件。如下图所示:

注:MyThread 继承于 QThread。

二、线程同步

1. 互斥量(Mutex)

        在多线程程序中,线程之间可能需要访问同一个变量(临界资源),或一个线程需要等待另一个线程完成某个操作才产生相应的动作。QMutexQMutexLocker 都是基于互斥量的线程同步类。

        QMutex lock() 函数用来锁定互斥量,unlock() 函数用来解锁互斥量。这两个方法必须配对使用。其次还要一个 tryLock() 函数,如果函数返回 true 则表示成拿到了共享资源。示例如下:

QMutex  mutex;void MyThread::run() {while(true) {mutex.lock();       //锁定互斥量...mutex.unlock();     //解锁互斥量} 
}

         QMutexLocker 和 QMutex 相比,是一个简化了互斥量处理的类。它的构造函数接受互斥量作为参数并将其锁定,其析构函数则将此互斥量解锁。QMutexLocker 会使其在生存期内的代码片段得到保护。示例如下:

QMutex  mutex;void MyThread::run() {while(true) {if (mutex.tryLock(500))    //尝试锁定一个信号量,最多等500ms{QMutexLocker locker(&mutex);    //锁定mutex,超出if范围自动解锁...  }} 
}

2. 读写锁(ReadWriteLock)

        使用互斥量时存在一个问题,那就是每次只有一个线程获得互斥量的使用权限。如果在一个程序中有多个线程读取某个变量,那么这个变量就不是临界资源,是允许同时访问的。这时我们就需要 Qt 提供的读写锁类 QReadWriteLock,它是基于读或写的方式进行代码片锁定的。

        其中 lockForRead() 函数会以只读方式锁定资源,锁定后其他线程只能读不能写。 lockForWrite() 函数以写的方式锁定资源,锁定后其他线程不能读也不能写。

3. 条件等待(WaitCondition)

        QWaitCondition 提供了一种改进的线程同步方法。它通过与 QReadWriteLock 结合使用,可以使一个线程在满足一定条件下通知其他多个线程,使其他多个线程即时进行响应。

        其中 wait() 函数用于释放互斥量,wakeAll() 函数用于唤醒所有处于等待状态的线程。wait() 函数定义如下:

bool wait(QReadWriteLock *readWriteLock, unsigned long time)

        QWaitCondition 一般用于生产者/消费者(producer/consumer)问题。暂且假设缓冲区一直有资源且无限大,示例代码如下:

QReadWriteLock rwLocker;    //读写锁QWaitCondition waiter;    //控制线程同步的对象// 生产者
void ProducerThread::run() {while(1) {rwLocker.lockForWrite();    //以写方式锁定...rwLocker.unlock();          //解锁waiter.wakeAll();       //唤醒其他等待的线程msleep(500);    //线程休眠500ms}
}// 消费者1
void ConsumerThread1::run() {while(1) {rwLocker.lockForRead();     //以只读方式锁定waiter.wait(&rwLocker);     //等待被唤醒...rwLocker.unlock();          //解锁}
}// 消费者2
void ConsumerThread2::run() {while(1) {rwLocker.lockForRead();     //以只读方式锁定waiter.wait(&rwLocker);     //等待被唤醒...rwLocker.unlock();          //解锁}
}

4. 信号量(Semaphore)

         信号量与互斥量类似,但二者又有区别。一个互斥量只能被锁定一次,而信号量可以被多次利用。信号量通常用来保护一定数量的相同资源,如双缓冲区。

        QSemaphore 就是 Qt 实现信号量功能的类。其中 acquire(int n) 用于尝试获得n个资源,release(int n) 用于释放n个资源。available() 用于返回当前信号量的可用资源个数。

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

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

相关文章

计算机网络408考研 2014

1 计算机网络408考研2014年真题解析_哔哩哔哩_bilibili 1 111 1 11 1

MyBatis:Maven,Git,TortoiseGit,Gradle

1,Maven Maven是一个非常优秀的项目管理工具,采用一种“约定优于配置(CoC)”的策略来管理项目。使用Maven不仅可以把源代码构建成可发布的项目(包括编译、打包、测试和分发),还可以生成报告、生…

短视频SDK,支持Flutter跨平台框架,加速产品上线进程

在数字内容爆炸式增长的今天,短视频已成为连接用户、传递情感、展现创意的重要桥梁。为助力开发者快速融入这股潮流,美摄科技匠心打造了一款专为Flutter框架优化的短视频SDK解决方案,旨在降低技术门槛,加速产品迭代,让…

主题与分区

主题和分区是Kafka的两个核心概念,分区的划分不仅为Kafka提供了可伸缩性、水平扩展的功能,还通过多副本机制来为Kafka提供数据冗余以提高数据可靠性。 主题创建 主题和分区都是提供给上层用户的抽象,而在副本层面或更加准确地说是Log层面&a…

Unity效果优化之抗锯齿

Unityde 基于HDRP渲染管线的抗锯齿处理的设置参考图: 前提:需要导入HDRP的插件包才行, 该参数设置能保证在PC版上抗锯齿效果非常好, 英文版:

AWS Lambda 十年回顾:功能总览、更新记录与入门指南

这次,我为2014年11月发布的AWS Lambda创建了一个历史时间表。AWS Lambda 是一项无服务器、全托管的代码执行服务,今年2024年11月将迎来其宣布发布的十周年纪念。虽然提前了一些,但为了提前庆祝这一重要时刻,我写了这篇文章。 文章…

论文解读 | ACL 2024:自我蒸馏在语言模型微调中架起分布差异的桥梁

点击蓝字 关注我们 AI TIME欢迎每一位AI爱好者的加入! 杨兆瑞 浙江大学CAD&CG全国重点实验室博士生 导师为陈为教授 概述 大型语言模型(LLMs)的兴起彻底改变了自然语言处理领域,但对它们进行特定任务的微调常常面临在平衡性能…

C++ | (一)C++入门基础

从本篇文章开始,我们正式进行C的系统学习。C是在C语言的基础上添加了面向对象编程的特性,是C语言的延伸,并遵循C语言的绝大多数语法。如果想学习C,必须要有一定的C语言基础,这样学起来才不会太过痛苦。 本文章即假设读…

【实战】Spring Security Oauth2自定义授权模式接入手机验证

文章目录 前言技术积累Oauth2简介Oauth2的四种模式授权码模式简化模式密码模式客户端模式自定义模式 实战演示1、mavan依赖引入2、自定义手机用户3、自定义手机用户信息获取服务4、自定义认证令牌5、自定义授权模式6、自定义实际认证提供者7、认证服务配置8、Oauth2配置9、资源…

【数据结构】—— 队列

1、队列的概念2、队列的结构如何选择合适的数据结构实现队列(数组or链表) 3、队列的链式存储3.1 队列的链式存储结构3.2 队列的常见接口3.3 队列的接口实现初始化判空入队列出队列获取队头元素获取队尾元素获取节点个数销毁 3.4 源代码 4、队列的顺序存储…

k8s持久化存储PV和PVC

一、PV和PVC 1.PersistentVolume (PV) PersistentVolume (PV) 是外部存储系统中的⼀块存储空间,由管理员创建和维护。与 Volume⼀样, PV 具有持久性,⽣命周期独⽴于 Pod; 2.PersistentVolumeClaim (PVC) PersistentVolumeClaim…

散点图、折线图 -- 通过javascript实现

散点图 散点图适合用于探索数据大局、比较值、发现趋势、模式和变量间关系&#xff0c;是数据分析中直观展示和初步探索的有力工具。 代码&#xff1a; <!DOCTYPE html> <html> <script src"https://cdn.plot.ly/plotly-latest.min.js"><…

如何快速实现MODBUS TCP转Profinet——泗博网关EPN-330

泗博网关EPN-330可作为PROFINET从站&#xff0c;支持与西门子S7-200 SMART/300/400/1200/1500全系列PLC以及具有PROFINET主站的系统无缝对接&#xff0c;而Modbus TCP端&#xff0c;可以与Modbus TCP从站设备、主站PLC、DCS系统以及组态软件等进行数据交互。 通过EPN-330&…

SemanticKernel/C#:实现接口,接入本地嵌入模型

前言 本文通过Codeblaze.SemanticKernel这个项目&#xff0c;学习如何实现ITextEmbeddingGenerationService接口&#xff0c;接入本地嵌入模型。 项目地址&#xff1a;https://github.com/BLaZeKiLL/Codeblaze.SemanticKernel 实践 SemanticKernel初看以为只支持OpenAI的各…

近似算法:求Π的近似值(迭代法)

问题&#xff1a;请用正多边形逼近法求Π的近似值。 算法&#xff1a;圆的周长 正多边形的边长 * 边数。设圆的半径为1&#xff0c;则2Π i * x 。其中 i 为正多边形边数&#xff0c;x 为边长。 因为圆的半径 内接于此圆的正六边形的边长&#xff0c;故从六边形开始计算。参…

git系统学习

git系统学习 git命令行获取git 版本号 创建初始版本库创建git库初始化用户名和密码查看用户名和邮箱修改用户名和密码 将文件添加到版本库中删除暂存文件提交代码查看提交信息查看更加详细的信息查看提交差异版本库内文件的删除和重命名删除库里的文件重命名库里的文件 打标签查…

重启人生计划-大梦方醒

&#x1f973;&#x1f973;&#x1f973; 茫茫人海千千万万&#xff0c;感谢这一刻你看到了我的文章&#xff0c;感谢观赏&#xff0c;大家好呀&#xff0c;我是最爱吃鱼罐头&#xff0c;大家可以叫鱼罐头呦~&#x1f973;&#x1f973;&#x1f973; 从今天开始&#xff0c;我…

MybatisPlus——扩展功能(一)

扩展功能 1.代码生成 在使用MybatisPlus以后&#xff0c;基础的Mapper、Service、PO代码相对固定&#xff0c;重复编写也比较麻烦。因此MybatisPlus官方提供了代码生成器根据数据库表结构生成PO、Mapper、Service等相关代码。只不过代码生成器同样要编码使用&#xff0c;也很麻…

软考高级:真实的程序、核心程序、小型基准程序、合成基准程序

一、AI 讲解 这段内容描述了在软件测试或性能测试中&#xff0c;不同类型程序的测试精确度排名。 测试类型说明精确度排名真实的程序直接测试实际运行的软件或系统&#xff0c;能够反映真实的使用场景1核心程序测试系统或应用的核心模块或功能&#xff0c;虽然范围较小但仍具…

使用Selenium调试Edge浏览器的常见问题与解决方案

背景介绍 在当今互联网时代&#xff0c;网页爬虫已经成为数据获取的重要手段。而Selenium作为一款功能强大的自动化测试工具&#xff0c;被广泛应用于网页爬取任务中。虽然Chrome浏览器是Selenium用户的常见选择&#xff0c;但在某些工作环境中&#xff0c;我们可能需要使用Ed…