【Qt线程-1】this,volatile,exec(),moveToThread()

2023-05-16

背景:

个人学习多线程控制,写了一些博文用于记录:

【Qt线程-2】事件循环(QCoreApplication::processEvents,exec)的应用

【Qt线程-3】使用事件循环,信号,stop变量,sleep阻塞,QWaitCondition+QMutex条件变量,退出子线程工作

【Qt线程-4】事件循环嵌套,BlockingQueuedConnection与QWaitCondition比较

【Qt线程-5】生产者&消费者模型应用(多态,子线程控制,协同,事件循环)

线程对象和线程执行

两者不是一回事。很多人说法不同,但都是一个意思。为了叙述方便,姑且称之为子线程,因为所有多线程处理,都是相对于主线程而言的。

比如在主线程中新开一个线程,需要类似这样的操作:

QThread *thd = new Qthread;

当然有时候是从Thread派生一个自定义的线程类。就如在主线程里创建一个对象没两样。

所以thd仅仅是主线程中的一个对象,thd这个对象,是用来管理子线程的。亦即,谁要操作这个子线程,必定要通过thd来操作,比如:

thd.start();
thd.stop();
thd.quit();
thd.wait();
thd.deleteLater();
...

就如操作某个控件一样来操作子线程。有点类似于windows的句柄。

因此,在定义thd的类代码中,所有成员变量和函数,都是在thd这个对象当中。如果没有run函数的参与,都会运行于主线程中。例如写个槽函数之类,相当于还是运行于主线程。

千万不能认为发给thd一个信号,只要它响应就应该是运行于子线程,这是不对的。

善用QDebug

在恰当位置输出信息,比如:

qDebug() << "frmMain::f_ClientConnect():The main thread is:"

                << this->thread()->currentThreadId();

qDebug() << "ThreadConn::f_ConnectCome() runs on thread:"

                << this->currentThreadId();

qDebug() << "ThreadConn::f_ConnectCome():tcpSocket runs on thread:"

                << m_tcpSocket->thread()->currentThreadId();

在调试时可以随时看到指定位置跑在哪个线程。

run()函数

run函数相当于真正线程过程的入口。所以通过run启动执行的代码,才是跑在子线程中。run函数调用的所有代码执行完,线程就完了。而这些通过run调用的代码,是可以使用thd类中定义的变量的。

this指针

在thd子线程的类代码中,this指针指向的是thd对象,它的parent是主线程,所以this其实是工作于主线程的。这点必须要理解,不是说在线程代码中使用this,就表示子线程了。

举个例子,如果在子线程中新建一个对象,像这样:

QObject *obj = new QObject(this);

开始我这样写也觉得没什么不妥,后来发现会报错的。思考之后才知道不能这样写,因为这相当于在子线程里创建一个属于主线程的对象,于是会有类似如下这样的提示:

Cannot create children for a parent that is in a different thread.

所以如果真的需要在子线程创建对象,去掉那个this就好了,如:

QObject *obj = new QObject();

exec和moveToThread

run函数中写个exec,是系统的事件循环,类似于死循环,但它占用资源很小。它可以让run保持运行,不是阻塞,它可以随时接收系统事件,但这个事件不是随便发个信号它就能响应的。

如果一个线程已经在运行,某个时刻希望有代码加入到exec的队列中,就写个子类,定义好响应信号的槽函数。实例化对象,比如叫obj,使用obj.moveToThread(thd)将它移动到子线程thd。然后给obj发信号让它响应就可以了。此时,obj当中的槽响应代码是可以加入exec的响应队列,它是在子线程中执行的。

Qt官方帮助这样写:

void QObject::moveToThread(QThread *targetThread)

Changes the thread affinity for this object and its children. The object cannot be moved if it has a parent. Event processing will continue in the targetThread.

……

我英文就不好,但是从学习linux和qt以来,发现有些帮助写的其实挺好理解的,主要是这些词都认识,不认识就百度翻译,见多就记住了。

volatile

这是个很好的关键字,看操作系统教科书上的代码,总有while (true){}这种死循环,然后通过判断某个变量决定是否跳出。但是单线程里直接这样写就真的死循环了。好像那个作为判断条件的变量不是那么理想化的。

线程代码里定义某个变量当做标记时,加上volatile关键字,例如这样:

volatile bool b = false;

这样它就听话了。至于为什么,直接网上搜索关键字volatile,各种好文章说的很到位。有位朋友这样写:

“线程之间的可见性,一个线程修改的状态对另一个线程可见,也就是一个线程修改的结果,另一个线程马上就能看到。”

已经很好理解了。这属于内存问题,如果不想深入理解,会用即可。

其实我试过,不用volatile貌似也能用。但有些时候又是必要的,所以是否需要使用,自己斟酌。

参考:C/C++ 中 volatile 关键字详解https://www.runoob.com/w3cnote/c-volatile-keyword.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【Qt线程-1】this,volatile,exec(),moveToThread() 的相关文章

随机推荐

  • Android viewBinding让你告别findViewById和ButterKnife

    很久没有更新博客了 xff0c 不是因为别的 xff0c 就是懒 今天要分享的一个新技术 xff0c 从此告别定义一大串的UI控件变量 xff0c 再也不用写findViewById xff0c 也不需要依赖ButterKnife和写一堆
  • 编译OpenCV 4.7.0 无法解析的外部符号 cv::xfeatures2d::VGG::getDefaultName 问题解决

    最近做特征匹配 xff0c 需要用到xfeatures2d中的特征 xff0c 源码编译OpenCV 4 7 0及opencv contrib 4 7 0中的xfeatures2d模块 xff0c 在Visual Studio 2019中编
  • 记一次在Taro开发的微信小程序中使用lottie动画的经验

    前景提要 最近在做公司项目的时候 xff0c 看到移动端开发用的小图标有动态效果 xff0c 非常好玩了解到是使用lottie进行实现的 xff0c 这个东西以前有看到过对应的插件库 xff0c 但是一直没有时间做研究 xff0c 趁着这个
  • JDB调试Android程序(通过JDB进行代码注入)

    前言 最近在做一些安卓安全相关的事情 xff0c 就看到了一个通过动态调试进行代码注入的一个概念 xff0c 收益匪浅 xff0c 原来好多东西还能这么玩的 闲言少絮 xff0c 开始正式行动 漏洞检查 由于我这边是做的关于安卓安全相关的事
  • [2019.12.20]strncpy发生stack corruption detected(-fstack-protector)栈溢出

    代码 char line MAX 61 0 strncpy line pBeginObj ptemp pBeginObj 43 1 log如下 解释 char strncpy char dest const char src int n 把
  • libmng.so.1: cannot open shared object file: No such file or directory

    span class token function sudo span span class token function ln span s usr lib x86 64 linux gnu libmng so 2 usr lib x86
  • 企业级数据模型主题域模型划分( IBM-FSDM)

    一 前言 如何构建主题域模型原则是构建企业级数据仓库重要的议题 xff0c 最好的路径就是参照成熟的体系 IBM金融数据模型数据存储模型FSDM xff0c 是金融行业应用极为广泛的数据模型 xff0c 可以作为我们构建企业级数据仓库主题域
  • 关于编程学习上的一些感悟——不忘初心

    序 今天无意中看到以前一起开发过的同学写的技术文章 xff0c 了解到了更多在blog和github以及一些技术交流论坛上面非常活跃 回过头来看看自己 xff0c 好像依然停留在以前的样子 xff0c 似乎与真正在踏实学技术差距好像很大了
  • CentOS下ns-3安装教程

    首先 xff0c 安装ns 3时最好不要使用root权限 xff0c 普通用户安装即可 xff0c 否则后来要找文件会比较麻烦 一 安装依赖软件包 首先安装依赖软件包 根据官网 xff08 https www nsnam org wiki
  • 生产者-消费者模型

    文章来自https github com NieJianJian AndroidNotes xff0c 内容将持续更新 xff0c 欢迎star 一 前言 生产者消费者模式并不是GOF提出的23种设计模式之一 xff0c 23种设计模式都是
  • JAVA 多线程解决高并发、超时线程池耗尽问题

    第一类 问题 项目中遇到了 创建20个固定线程的线程池 在测试环境 多线程如果高并发的调用都没出现问题 但是在实际的项目中 出现了线程池内线程超时等待并将池内的线程耗尽 导致其它的程序走到多线程调用时候出现了执行慢 线程无法执行问题 问题原
  • 31_谈谈你对线程安全的理解?(重点)

    如果这个是面试官直接问你的问题 xff0c 你会怎么回答 xff1f 一个专业的描述是 xff0c 当多个线程访问一个对象时 xff0c 如果不用进行额外的同步控制或其他的协调操作 xff0c 调用这个对象的行为都可以获得正确的结果 xff
  • MariaDB 数据类型

    MariaDB 数据类型 数字数据类型 MariaDB支持的数字数据类型如下 类型描述TINYINT此数据类型表示落入 128到127的有符号范围内的小整数 xff0c 以及0到255的无符号范围 BOOLEAN此数据类型将值0与 fals
  • DBSCAN算法(python代码实现)

    DBSCAN 上次学了kmeans基于划分的方法 xff0c 这次学一个基于密度的聚类算法 xff1a DBSCAN xff08 Density Based Spatial Clustering of Applications with N
  • vs2022(缺少MFC,无法新建项目,控件无法添加事件)的解决

    最近下载安装了最新的vs2022社区版 xff0c 想着把之前的c 43 43 项目能够兼容 xff0c 于是遇到了一些列问题 缺少MFC xff0c 无法新建项目 xff0c 控件无法添加事件 这里首先要吐槽一下 xff1a 也许是我电脑
  • C#多线程加载控件界面卡死的解决

    先听一个故事 xff1a 有一个老板忙不过来 xff0c 于是招一个员工去负责某些事务 这样老板就可以腾出时间处理其它事 后来发现员工干不下去 xff0c 原因是干活需要花费 xff0c 没有老板的认可 xff0c 财务不给批钱 这是原则
  • vs2022账户无法登录的解决

    因为昨天重做系统 xff0c 重装了vs2022 xff0c 又涉及到登录的问题 xff0c 一时想不起来之前怎么解决的了 xff0c 想起来以后决定还是记录下来 我遇到的问题是下面这样的 xff0c 提示脚本错误 xff0c 要求升级最新
  • 使用centos7+bind9构建内网私有dns

    有这样一种场景 xff0c 局域网内有一个为网内用户提供服务的机器 xff0c 我们希望像访问互联网站点一样去访问它 xff0c 而不用记忆ip地址和端口 xff0c 比如在web浏览器地址栏输入http www nx com就可以访问它
  • PowerBuilder制作纸牌游戏

    本文记录的是2001年我大三那年假期制作小游戏的思路 xff0c 希望给在读计算机专业的朋友们一些参考 xff0c 如果还没来得及动手尝试的同学 xff0c 一定要勇于动手 你们一定比我做得更好 制作动力 xff1a 我有一个好朋友 xff
  • 【Qt线程-1】this,volatile,exec(),moveToThread()

    背景 xff1a 个人学习多线程控制 xff0c 写了一些博文用于记录 xff1a Qt线程 2 事件循环 xff08 QCoreApplication processEvents xff0c exec xff09 的应用 Qt线程 3 使