Qt:多线程

目录

初识Qt多线程

QThread常用API

QThread的使用

Qt中的锁

条件变量和信号量


初识Qt多线程

Qt 多线程 和 Linux 中的线程本质是一个东西
Linux 中学过的 多线程 APl,Linux 系统提供的 pthread 库
Qt 中针对系统提供的线程 API 重新封装了
C++11 中,也引入了线程 std:thread

Qt API 设计的时候,博采众家之长:

  • Linux 原生的多线程 API,设计的非常差,使用起来非常不方便的(也是C语言本身的局限性引起的)
    实际开发中,很少会使用原生 api
  • C++ 的 std::thread 要比 Linux 的 API 要好一些
  • Qt 中的多线程 API,还要更好一点,其实参考了 Java 中的线程库 API 的设计方式

在 Qt 中,多线程的处理一般是通过 QThread类 来实现
QThread 代表一个在应用程序中可以独立控制的线程,也可以和进程中的其他线程共享数据
OThread 对象管理程序中的一个控制线程

QThread要想创建线程,就需要创建出这样类的实例
创建线程的时候,需要重点指定线程的入口函数

Qt中,使用方式就是创建一个 QThread 的子类,重写其中的 run 函数,起到指定入口函数的方式(多态)


QThread常用API


QThread的使用

之前基于定时器,写过倒计时这样的程序,也可以通过线程,来完成类似的功能
定时器内部本质上也是可以基于多线程来实现的(Qt 的定时器是否基于多线程,不太清楚)

创建另一个线程,新线程中进行计时(搞一个循环,每循环一次,sleep 1s,sleep 完成,就可以更新界面了)

首先图形化界面的方式拖动一个 LCD Number,初始值设为10:

接下来创建一个类 Thread,继承自 QThread:

由于存在线程安全问题,多个线程同时对于界面的状态进行修改,此时就会导致界面就出错了
Qt 选择了 一刀切,针对界面的控件状态进行任何修改,务必在主线程中执行

在 thread.h 中,声明需要重写的 run 函数,再声明一个信号:

run 函数的实现:

接着在 widget.h 中创建一个 Thread 对象 thread,和一个处理信号的槽函数 handle:

Widget 构造函数如下:

槽函数 handle:

此时运行程序,就完成了倒计时的功能:

下面总结一下执行流程:

  • 主线程启动新线程
  • 新线程每隔一秒发送一次信号
  • 主线程收到信号后,调用槽函数修改倒计时的值

Qt中的锁

说起多线程,最需要注意的就是线程安全问题,因为多线程程序太复杂了

而解决线程安全问题,最主要的措施就是加锁

把多个线程要访问的公共资源,通过锁保护起来  =>  把并发执行变成串行执行

关于锁,Linux、C++、Qt 都有一套规定:

  • Linux:mutex 互斥量
  • C++11 引入 std:.mutex
  • Qt 同样也提供了对应的锁 QMutex,来针对系统提供的锁进行封装
    与 C++ 的 std:.mutex 相差不大,lock 加锁,unlock 解锁

下面演示 Qt 中锁的使用

创建好项目后,同样创建一个新的类 Thread,继承自 QThread:

因为下面想要两个线程对同一个变量进行操作,所以在 Thread 中添加一个静态成员 num,并声明重写的 run 方法:
注意 num 需要类内声明,类外初始化(在 thread.cpp 中初始化:int Thread::num = 0;)

run 方法就是循环5万次,每次给 num++:

下面在 widget.cpp 中编写构造函数的逻辑:

此时打印的结果如下:


并不是我们预期的10万,说明是存在 bug,说明是存在线程安全问题的

所以需要加锁处理,为了让两个线程用同一把锁,就将这个锁设为 static 的:
同样需要在 thread.cpp 中定义:QMutex Thread::mutex;

有了锁 mutex 后,就可以在 run 函数中 num++ 前后进行加锁和解锁操作:

此时再次运行程序,num 的值就是我们期望的10万了:


上面虽然结果正确了,但是这里的锁很容易忘记释放,忘记 unlock

实际开发中,加锁之后涉及到的逻辑可能很复杂,下面很容易就忘记释放锁

在 C++ 中释放动态内存也存在类似的问题,在释放前如果有 return 或 抛异常,就会出问题

C++ 在内存这里采用智能指针进行处理,而锁的释放,C++11 引入了 std::lock_guard,就相当于是 std::mutex 的智能指针,也是借助 RAII 机制

所以 std::lock_guard 一般如下所示:

{std::lock_guard(mutex);// 执行各种逻辑
}
大括号执行完毕, guard 变量的生命周期结束,就会在析构的时候,执行 unlock 了

上述方案,Qt也参考过来了,即 QMutexLocker

所以上述的 run 函数改为:

此时每次循环结束,locker 就会自动解锁,每次进入循环又会自动加锁,不会出现忘记解锁,或是有 return 和 异常 跳过解锁的情况

运行程序,依旧能够执行出正确的结果:

注意:

Qt 的锁 和 C++ 标准库中的锁,本质上都是封装的系统提供的锁
编写多线程程序的时候,可以使用 Qt 的锁,也可以使用 C++的锁,C++的锁也是可以锁 Qt 的线程的(虽然混着用也行,一般不建议)


条件变量和信号量

这里的条件变量和信号量,和 Linux 中谈到的条件变量/信号量完全一致

条件变量

多个线程之间的调度是无序的,为了能够一定程度的干预线程之间的执行顺序,引入条件变量

QWaitCondition

  • wait
  • wake
  • wakeAll

要想使用条件变量,首先要进行加锁,因为在 wait 中就会进行 释放锁 + 等待
要想释放锁, 前提就是先获取到锁

并且还要搭配 while 循环,判断条件是否成立:

// 判定线程继续执行的条件是否成立,不成立就进行 wait 等待
while(!conditionFullfilled())
{condition.wait(&mutex);//等待条件满足并释放锁
}

这里要使用while 判定而不是 if,是因为:
唤醒之后,需要再确认一下当前条件是否真的成立了,wait 可能被提前唤醒的(可能被信号打断了)


信号量

这里谈到的信号量,其实还可以进行进程之间的控制
当然,也同样可以作为同一个进程内部的线程之间的通信方式

信号量其实就是计数器,描述了可用资源的个数

使用示例:

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

Qt:多线程相关到此结束

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

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

相关文章

如何用Kimi生成PPT?秒出PPT更高效!

做PPT是不是总是让你头疼?😩 快速制作出专业的PPT,今天我们要推荐两款超级好用的AI工具——Kimi 和 秒出PPT!我们来看看哪一款更适合你吧!🚀 🥇 Kimi:让PPT制作更轻松 Kimi的生成效…

计算机毕业设计SpringBoot+Vue.js车辆管理系统(源码+文档+PPT+讲解)

温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 作者简介:Java领…

机器学习4-PCA降维

1 降维 在数据处理过程中,会碰到维度爆炸,维度灾难的情况,为了得到更精简更有价值的信息,我们需要进一步处理,用的方法就是降维。 降维有两种方式:特征抽取、特征选择 特征抽取:就是特征映射…

探秘沃尔什-哈达玛变换(WHT)原理

沃尔什-哈达玛变换(WHT)起源 起源与命名(20世纪早期) 数学基础:该变换的理论基础由法国数学家雅克哈达玛(Jacques Hadamard)在1893年提出,其核心是哈达玛矩阵的构造。扩展与命名&…

使用 vxe-table 导出 excel,支持带数值、货币、图片等带格式导出

使用 vxe-table 导出 excel,支持带数值、货币、图片等带格式导出,通过官方自动的导出插件 plugin-export-xlsx 实现导出功能 查看官网:https://vxetable.cn gitbub:https://github.com/x-extends/vxe-table gitee:htt…

uniapp实现的个人中心页面(仿小红书)

采用 uniapp 实现的一款仿小红书个人中心页面模板,支持vue2、vue3, 同时适配H5、小程序等多端多应用。 简约美观大方 可到插件市场下载尝试: https://ext.dcloud.net.cn/plugin?id22516 示例

步进电机软件细分算法解析与实践指南

1. 步进电机细分技术概述 步进电机是一种将电脉冲信号转换为角位移的执行机构,其基本运动单位为步距角。传统步进电机的步距角通常为 1.8(对应 200 步 / 转),但在高精度定位场景下,这种分辨率已无法满足需求。细分技术…

tauri-plugin-shell插件将_blank的a标签用浏览器打开了,,,解决办法

不要使用这个插件,这个插件默认会将网页中a标签为_blank的使用默认浏览器打开,但是这种做法在我的程序里不是很友好,我需要自定义这种行为,当我点击我自己的链接的时候,使用默认浏览器打开,当点击别的链接的…

ESP8266 NodeMCU 与 Atmega16 微控制器连接以发送电子邮件

NodeMCU ESP8266 AVR 微控制器 ATmega16 的接口 Atmega16 是一款低成本的 8 位微控制器,比以前版本的微控制器具有更多的 GPIO。它具有所有常用的通信协议,如 UART、USART、SPI 和 I2C。由于其广泛的社区支持和简单性,它在机器人、汽车和自动化行业有广泛的应用。 Atmega1…

C++查看动态库导出哪些函数以及动态库导出形式

1、查看动态库导出哪些函数 1.1、在 Windows 和 Linux 上,可以使用不同的方法来查看动态库(.dll 或 .so)导出的函数 Windows:使用 dumpbin:Windows 提供了 dumpbin 工具(Visual Studio 自带)&…

【使用hexo模板创建个人博客网站】

使用hexo模板创建个人博客网站 环境准备node安装hexo安装ssh配置 使用hexo命令搭建个人博客网站hexo命令 部署到github创建仓库修改_config.yml文件 编写博客主题扩展 环境准备 node安装 进入node官网安装node.js 使用node -v检查是否安装成功 安装成功后应该出现如上界面 …

【Linux】http 协议

目录 一、http协议 (一)http 协议的概念 (二)URL的组成 (三)urlencode 和 urldecode 二、http 的协议格式 (一)http 请求方法 (二)http 响应状态码 &a…

什么是时序数据库?有哪些时序数据库?常见的运用场景有哪些?

时序数据库 什么是时序数据库? 时序数据库(Time Series Database, TSDB)是专门针对时间序列数据(按时间顺序记录的数据点)进行存储和管理的数据库。这类数据通常包含时间戳(Timestamp)和对应的…

【Linux】冯诺依曼体系与操作系统理解

🌟🌟作者主页:ephemerals__ 🌟🌟所属专栏:Linux 目录 前言 一、冯诺依曼体系结构 二、操作系统 1. 操作系统的概念 2. 操作系统存在的意义 3. 操作系统的管理方式 4. 补充:理解系统调用…

Unity HDR颜色、基础颜色、强度强度、HDR面板Intensity之间的相互转换

目录 前言: 一、UnityHDR面板的规律 二、HDR与基础颜色转换,HDR强度获取,输入设置强度获取 1.基础色->HDR颜色 2.HDR颜色->基础色 3.获取HDR颜色在面板中的强度 4.获取HDR颜色在面板设置输入时的强度 前言: HDR&#…

c++进阶--map和set的使用

大家好,昨天我们学习了二叉搜索树,今天我们来学习一下map和set容器的使用。 目录 1. map和set的使⽤ 1.1 序列式容器和关联式容器 2. set系列的使⽤ 2.1 参考文档 2.2 set类的介绍 2.3 set的构造和迭代器 2.4 set的增删查 2.5 insert和迭代器…

Kylin麒麟操作系统服务部署 | NFS服务部署

以下所使用的环境为: 虚拟化软件:VMware Workstation 17 Pro 麒麟系统版本:Kylin-Server-V10-SP3-2403-Release-20240426-x86_64 一、 NFS服务概述 NFS(Network File System),即网络文件系统。是一种使用于…

FPGA之USB通信实战:基于FX2芯片的Slave FIFO回环测试详解

FPGA之Usb数据传输 Usb 通信 你也许会有疑问,明明有这么多通信方式和数据传输(SPI、I2C、UART、以太网)为什么偏偏使用USB呢? 原因有很多,如下: 1. 高速数据传输能力 高带宽:USB接口提供了较高的数据传…

生活反思公园散步与小雨遇记

《公园散步与小雨遇记》(一) 总收录于《生活小事灵感反思》与《生活小美好》 最近又新增一个习惯:每天至少走一小时 那天天气有雨,软件上显示在下雨,但是外面没雨,心想着大不了淋湿回来洗个头,…

夏门大学DeepSeek 手册:从社会大众到高校及企业的全面应用实践研究(附 PDF 下载)

这 3 份手册分别从 DeepSeek 大模型概念、技术与应用实践、DeepSeek 大模型赋能高校教学和科研、DeepSeek 大模型及其企业应用实践-企业人员的大模型宝典几个角度进行全面分析,可以结合着清华、北大系列相互对照着学习。 清华北大推出的 DeepSeek 教程(…