系统讨论Qt的并发编程——逻辑上下文的分类
目录
前言
首先,讨论Qt里常见的三种上下文
同一线程的串行执行
同一线程的异步执行
多线程的执行
moveToThread办法
前言
笔者最近看了一个具备一定启发性质的Qt教程,在这里,笔者打算整理一下自己的笔记。分享在这里.
首先,讨论Qt里常见的三种上下文
Qt在逻辑层上,笔者认为可分成三种上下文:同线程的同步,同线程的异步和多线程。
一个典型的同线程之间的同步,说的是我们的处理在执行流上,是串行的。
main ---> A -----> B ------> C
比如说,A函数,B函数和C函数在上下文中,串行的执行。这样的上下文,非常的可靠,每一个指令流都串行的访问数据,不会出现数据竞争的问题,但是代价就是——非常的慢。笔者三年的编程经验告诉自己——这样的编程上下文,适用于流程在时序上非常严密的场景。
一个典型的同线程异步,事情就看起来很有趣了。实际上看起来像这样。

这样的技术,任何一个学习过OS的都知道,实际上是在应用层上对这个线程实现了分片,换而言之,我们在这个线程上实现了逻辑并行,物理串行的效果——看起来我们的代码在并发的执行,但是实际上是一个线程快无影的完成一大堆工作。所以,这样的编程范式属于高响应要求的场景,或者说,我们对性能谈不上太高的要求,只需要他们看起来在同时执行。

这个场景,就是真并发的场景了,不管怎么说,我们真的有多个线程执行多个代码流,我们的代码上下文被托付给了操作系统层级的线程完成我们的工作。我们老生长谈的数据竞争并发安全,就是在讨论这里的事情。
同一线程的串行执行
#include <QCoreApplication>
#include <QThread>
void workA() {qInfo() << "I am handling Work A" << "Thread:" << QThread::currentThread();QThread::currentThread()->sleep(1);qInfo() << "Work A Finished";
}
void workB() {qInfo() << "I am handling Work B" << "Thread:" << QThread::currentThread();QThread::currentThread()->sleep(1);qInfo() << "Work B Finished";
}
void workC() {qInfo() << "I am handling Work C" << "Thread:" << QThread::currentThread();QThread::currentThread()->sleep(1);qInfo() << "Work C Finished";
}
int main(int argc, char *argv[]) {QCoreApplication a(argc, argv);QThread::currentThread()->setObjectName("Thread Main");workA();workB();workC();return a.exec();
}
这个就是一个例子,我们的任务ABC按照串行依次执行代码。看我们的输出,就是这个主线程在依次的做任务ABC。
I am handling Work A Thread: QThread(0x1f0730e2860, name = "Thread Main")
Work A Finished
I am handling Work B Thread: QThread(0x1f0730e2860, name = "Thread Main")
Work B Finished
I am handling Work C Thread: QThread(0x1f0730e2860, name = "Thread Main")
Work C Finished
同一线程的异步执行
事实上,对于一些使用了QT类的场景,同一线程的异步执行仍然非常常见。一个经典的例子就是我们使用QTimer的singleshot办法触发一个函数的执行。你可以看到,我们实际上根本没有直接的调用,但是async_workA由于timer事件的通知作为槽执行了
#include <QCoreApplication>
#include <QThread>
#include <QTimer>
void async_workA() {qInfo() << "Lets's see the current thread: "<< QThread::currentThread()->objectName();QThread::currentThread()->sleep(1);qInfo() << "And A work done:)";
}
int main(int argc, char *argv[]) {QCoreApplication a(argc, argv);QThread::currentThread()->setObjectName("Main Thread");QTimer m;m.singleShot(1000, &async_workA);
qInfo() << "Main Thread: " << QThread::currentThread()->objectName();qInfo() << "has reached its end!";return a.exec();
}
多线程的执行
现在我们开始上难度,那就是多线程的执行。
TestObject.cpp
#include "TestObject.h"
#include <QDebug>
#include <QThread>
#include <QTimer>
TestObject::TestObject(QObject *parent) : QObject{parent} {}
void TestObject::runMe() {qInfo() << QThread::currentThread()->objectName() << " Running";QTimer::singleShot(1000, this, &TestObject::internel_shot);qInfo() << QThread::currentThread()->objectName() << " Finish";
}
void TestObject::internel_shot() { qInfo() << "Shot"; }
Main.cpp
#include <QCoreApplication>
#include <QThread>
#include "TestObject.h"
int main(int argc, char *argv[]) {QCoreApplication a(argc, argv);
QThread::currentThread()->setObjectName("Main Thread");
qInfo() << "Ready to shot a thread";
QThread thread;thread.setObjectName("Thread Worker");
TestObject test;
test.moveToThread(&thread);
QObject::connect(&thread, &QThread::started, &test, &TestObject::runMe);
thread.start();
qInfo() << "Finish " << QThread::currentThread()->objectName();
return a.exec();
}
这里有一个新的方法,简单说一下:
moveToThread办法
moveToThread 是 Qt 中用于将对象移到指定线程的函数。必须说明的是——我们的QT信号与槽机制是不跨线程的,也就是说,我们没办法使用信号与槽机制链接在A线程的a对象的信号与在B线程的b对象的槽。对于非 GUI 类的对象,可以通过调用 moveToThread 将它们从主线程或其他线程转移到目标线程。这样,目标线程就会负责该对象的事件处理和信号槽连接。
这样,我们就会将我们的TestObject放置到我们的新线程中,换而言之,任何一个将会在B线程工作但是创建于A线程的物体,请使用这个方法。
相关文章:
系统讨论Qt的并发编程——逻辑上下文的分类
目录 前言 首先,讨论Qt里常见的三种上下文 同一线程的串行执行 同一线程的异步执行 多线程的执行 moveToThread办法 前言 笔者最近看了一个具备一定启发性质的Qt教程,在这里,笔者打算整理一下自己的笔记。分享在这里. 首先,…...
《Linux Shell 脚本深度探索:原理与高效编程》
1. 基本结构 Shebang 行 #!/bin/bash # Shebang 行指定了脚本使用的解释器。 /bin/bash 表示使用 Bash 解释器执行脚本。 注释 # 这是注释,不会被执行 2. 变量 定义变量 variable_namevalue # 不需要加 $ 来定义变量。 # 变量名不能包含空格或特殊字符。 访…...
深入剖析:基于红黑树实现自定义 map 和 set 容器
🌟 快来参与讨论💬,点赞👍、收藏⭐、分享📤,共创活力社区。🌟 在 C 标准模板库(STL)的大家庭里,map和set可是超级重要的关联容器成员呢😎&#x…...
在大数据项目中如何设计和优化数据模型
在大数据项目中,设计和优化数据模型是一个涉及多个步骤和维度的复杂过程。以下是我通常采取的方法: 一、数据模型设计 明确业务需求: 深入了解项目的业务场景和目标,明确数据模型需要解决的具体问题。与业务团队紧密合作…...
JavaScript querySelector()、querySelectorAll() CSS选择器解析(DOM元素选择)
文章目录 基于querySelector系列方法的CSS选择器深度解析一、方法概述二、基础选择器类型1. 类型选择器2. ID选择器3. 类选择器4. 属性选择器 三、组合选择器1. 后代组合器2. 子元素组合器3. 相邻兄弟组合器4. 通用兄弟组合器 四、伪类与伪元素1. 结构伪类2. 状态伪类3. 内容伪…...
Linux系统中处理子进程的终止问题
1. 理解子进程终止的机制 在Unix/Linux系统中,当子进程终止时,会向父进程发送一个SIGCHLD信号。父进程需要捕捉这个信号,并通过调用wait()或waitpid()等函数来回收子进程的资源。这一过程被称为“回收僵尸进程”。 如果父进程没有及时调用w…...
Docker 不再难懂:快速掌握容器命令与架构原理
1. Docker 是容器技术的一种 容器(Container)概述 容器(Container)是一种轻量级的虚拟化技术,它将应用程序及其所有依赖环境打包在一个独立的、可移植的运行时环境中。容器通过操作系统级的虚拟化提供隔离࿰…...
取消票证会把指定的票证从数据库中删除,同时也会把票证和航班 等相关表中的关联关系一起删除。但在删除之前,它会先检查当前用户是否拥有这张票
在做航班智能客服问答系统时会遇到取消票证的场景,这里涉及数据库的操作时会把指定的票证从数据库中删除,同时也会把票证和航班等相关表中的关联关系一起删除。但在删除之前,需要先检查当前用户是否拥有这张票,只有票主才有权限取…...
力扣-贪心-763 划分字母区间
思路 先统计字符串中每一个字母出现的最后下标,然后从end初始化为第一个字母出现的最后下标,在i<end时,不断更新end,因为一旦囊括新的字母就最起码要遍历到新字母出现的最后下标,在i>end时,说明遍历…...
【Redis 原理】网络模型
文章目录 用户空间 && 内核空间阻塞IO非阻塞IO信号驱动IO异步IOIO多路复用selectpollepoll Web服务流程Redis 网络模型Redis单线程网络模型的整个流程Redis多线程网络模型的整个流程 用户空间 && 内核空间 为了避免用户应用导致冲突甚至内核崩溃,用…...
cpp中的继承
一、继承概念 在cpp中,封装、继承、多态是面向对象的三大特性。这里的继承就是允许已经存在的类(也就是基类)的基础上创建新类(派生类或者子类),从而实现代码的复用。 如上图所示,Person是基类&…...
DeepSeek全栈接入指南:从零到生产环境的深度实践
第一章:DeepSeek技术体系全景解析 1.1 认知DeepSeek技术生态 DeepSeek作为新一代人工智能技术平台,构建了覆盖算法开发、模型训练、服务部署的全链路技术栈。其核心能力体现在: 1.1.1 多模态智能引擎 自然语言处理:支持文本生成(NLG)、语义理解(NLU)、情感分析等计算…...
CSS 真的会阻塞文档解析吗?
在网页开发领域,一个常见的疑问是 CSS 是否会阻塞文档解析。理解这一问题对于优化网页性能、提升用户体验至关重要。要深入解答这个问题,需要从浏览器渲染网页的原理说起。 浏览器渲染网页的基本流程 浏览器在接收到 HTML 文档后,会依次进行…...
大模型的UI自动化:Cline 使用Playwright MCP Server完成测试
大模型的UI自动化:Cline 使用Playwright MCP Server完成测试 MCP MCP(Model Context Protocol),是一个开发的协议,标准化了应用程序如何为大模型提供上下文。MCP提供了一个标准的为LLM提供数据、工具的方式,使用MCP会更容易的构建Agent或者是基于LLM的复杂工作流。 最近…...
碰撞检测 | 图解凸多边形分离轴定理(附ROS C++可视化)
目录 0 专栏介绍1 凸多边形碰撞检测2 多边形判凸算法3 分离轴定理(SAT)4 算法仿真与可视化4.1 核心算法4.2 仿真实验 0 专栏介绍 🔥课设、毕设、创新竞赛必备!🔥本专栏涉及更高阶的运动规划算法轨迹优化实战,包括:曲线…...
Python 基本数据类型
目录 1. 字符串(String) 2. 列表(List) 3. 字典(Dictionary) 4. 集合(Set) 5. 数字(Number) 6. 布尔值(Boolean) 1. 字符串&…...
突破“第一崇拜“:五维心理重构之路
一、视频介绍 在这个崇尚"第一"的时代,我们如何找到自己的独特价值?本视频将带您踏上五维心理重构之旅,从诗意人生的角度探讨如何突破"圣人之下皆蝼蚁"的局限。我们将穿越人生的不同阶段,从青春的意气风发到…...
KubeKey一键安装部署k8s集群和KubeSphere详细教程
目录 一、KubeKey简介 二、k8s集群KubeSphere安装 集群规划 硬件要求 Kubernetes支持版本 操作系统要求 SSH免密登录 配置集群时钟 所有节点安装依赖 安装docker DNS要求 存储要求 下载 KubeKey 验证KubeKey 配置集群文件 安装集群 验证命令 登录页面 一、Ku…...
UE5网络通信架构解析
文章目录 前言一、客户端-服务器架构(C/S Model)二、对等网络架构(P2P,非原生支持)三、混合架构(自定义扩展)四、UE5网络核心机制 前言 UE5的网络通信主要基于客户端-服务器(C/S&am…...
实验3 知识表示与推理
实验3 知识表示与推理 一、实验目的 (1)掌握知识和知识表示的基本概念,理解其在AI中的深刻含义与意义; (2)熟悉AI中常用的知识表示方法的优缺点及其应用场景; (3)掌握产…...
【AGI物流落地倒计时】:为什么2026年Q2成为企业接入自主决策物流AI的最后窗口期?
第一章:2026奇点智能技术大会:AGI与物流管理 2026奇点智能技术大会(https://ml-summit.org) AGI驱动的动态物流决策中枢 在2026奇点智能技术大会上,多家头部物流企业联合发布了基于自主推理架构(Autonomous Reasoning Architect…...
03 原创AI大模型开源:华夏之光永存:华夏本源大模型——合规数据集处理与标准化训练方案
华夏之光永存:华夏本源大模型——合规数据集处理与标准化训练方案 一、本篇核心定位 本篇承接第二篇架构设计,全流程放出合规数据处理模型训练硬核实操内容,所有流程、参数、脚本逻辑均为可直接落地、可复现的开源干货,完全匹配7B…...
【代码】基于交替方向乘子法(admm)的微电网分布式低碳优化运行策略matlab-yalmip-cplex/gurobi
✅作者简介:热爱科研的Matlab仿真开发者,擅长毕业设计辅导、数学建模、数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。🍎 往期回顾关注个人主页:Matlab科研工作室👇 关注我领取海量matlab电子书和…...
别只发GET请求了!ESP32的HTTPClient库POST数据到服务器,保姆级配置流程(含模拟测试)
ESP32实战:HTTPClient库POST数据全流程指南与模拟测试方案 在物联网开发中,数据采集只是第一步,如何将传感器数据可靠地上传到服务器才是真正体现项目价值的环节。很多开发者习惯使用GET请求获取数据,却忽视了POST请求在数据上传中…...
【编译原理实战】语法制导翻译:从SDD/SDT理论到抽象语法树构建
1. 语法制导翻译:编译器背后的隐形推手 第一次接触语法制导翻译(Syntax-Directed Translation)时,我正试图给自制的脚本语言添加类型检查功能。当时手动维护符号表的痛苦经历让我意识到:需要一套系统化的方法将语法结构…...
【多源融合】Sage-Husa自适应滤波:从理论推导到工程实践
1. Sage-Husa自适应滤波:从数学公式到工程落地 第一次接触Sage-Husa滤波时,我也被满屏的矩阵运算搞得头晕眼花。但当我真正把它用在无人机导航系统里,才发现这套算法的精妙之处——它能让滤波器在传感器性能波动时保持稳定输出。想象一下你的…...
保姆级避坑指南:在Ubuntu 20.04上搞定ego-planner与PX4仿真(解决eigen3版本冲突)
Ubuntu 20.04下ego-planner与PX4仿真的深度避坑手册 当你在深夜的实验室里,面对满屏红色报错信息时,是否也曾怀疑人生?作为过来人,我完全理解那种在搭建ego-planner三维路径规划环境时的崩溃感。本文将带你穿越这片"雷区&quo…...
SSD-PyTorch训练自定义数据集避坑指南:从VOC格式准备到模型调参全流程
SSD-PyTorch实战:自定义数据集训练避坑与性能优化全解析 第一次用SSD训练自己的目标检测模型时,我盯着报错信息发呆了半小时——明明按照教程操作,却在数据加载环节卡住。后来才发现是PyTorch版本差异导致的API变更。这种"看似简单实则暗…...
Windows 11终极优化指南:免费开源工具Win11Debloat让系统重获新生
Windows 11终极优化指南:免费开源工具Win11Debloat让系统重获新生 【免费下载链接】Win11Debloat A simple, lightweight PowerShell script that allows you to remove pre-installed apps, disable telemetry, as well as perform various other changes to declu…...
别再死记F-22/FB60了!SAP F-02超级凭证的记账码(Posting Key)保姆级使用指南
SAP F-02超级凭证记账码实战指南:告别机械记忆,掌握底层逻辑 每次打开SAP系统准备录入凭证时,财务顾问们总会面临一个经典困境:是该用F-22处理客户发票,还是FB60录入供应商账单?这种对特定事务码的依赖不仅…...
