Qt——多线程

ops/2024/10/18 14:25:04/

一、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.ppmy.cn/ops/94363.html

相关文章

数据操作语言(DML)

SQL常用语句--超实用!!! 数据操作: 1.插入数据(数据需要一一对应) INSERT INTO employees (employee_id,name,age,department_id) VALUES(1,John Doe,30,5); 2.更新数据 UPDATE employees SET name Jane Doe WHERE employee_i…

【图论】并查集(Union-find Sets)

文章目录 前言一、并查集(Union-find Sets)基本概念基本操作步骤 二、并查集的操作步骤1. 初始化 init2. 查询 find、合并 union(未进行路径压缩)3. 查询 find、合并 union(路径压缩) 三、Kruskal 算法中 环 的判断并查集的使用 总…

leetcode线段树(2940. 找到 Alice 和 Bob 可以相遇的建筑)

前言 经过前期的基础训练以及部分实战练习&#xff0c;粗略掌握了各种题型的解题思路。现阶段开始专项练习。 描述 给你一个下标从 0 开始的正整数数组 heights &#xff0c;其中 heights[i] 表示第 i 栋建筑的高度。 如果一个人在建筑 i &#xff0c;且存在 i < j 的建筑…

链表(哈希表,有序表)环形链表确定节点的方式

UnOrderedMap UnSortedMap --> C 哈希表&#xff08;无序组织&#xff09; 哈希表如果只有key 没有 value 是HashSet 哈希表如果有key 有 value 是HashMap 哈希表在使用的过程中所有的增删改查都是常数时间&#xff08;比较大&#xff09; 如果存放的是基础类型&#xf…

【Python机器学习】回归——示例:预测乐高玩具套装的价格

用回归法预测乐高套装价格的基本步骤&#xff1a; 1、收集数据&#xff1a;用Google Shopping的API收集到的数据 2、准备数据&#xff1a;从返回的JSON数据中抽取价格 3、分析算法&#xff1a;可视化并观察数据 4、训练算法&#xff1a;构建不同的模型&#xff0c;采用逐步线性…

书生.浦江大模型实战训练营——(三)Git基本操作与分支管理

最近在学习书生.浦江大模型实战训练营&#xff0c;所有课程都免费&#xff0c;以关卡的形式学习&#xff0c;也比较有意思&#xff0c;提供免费的算力实战&#xff0c;真的很不错&#xff08;无广&#xff09;&#xff01;欢迎大家一起学习&#xff0c;打开LLM探索大门&#xf…

Cannot connect to the Docker daemon at unix:///var/run/docker.sock. 问题解决

问题描述 原来我的服务器docker服务运行正常&#xff0c;但在某次尝试用时, 根据系统的错误提示执行了snap install docker指令之后&#xff0c; 再执行docker ps命令则提示Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running…

C语言strpbrk函数

目录 开头1.什么是strpbrk函数?2.strpbrk函数的内部程序流程图 3.strpbrk函数的实际应用定位字符串中的字符求元音字母(a e i o u A E I O U)的个数NB158 牛牛的名字游戏 结尾 开头 大家好&#xff0c;我叫这是我58。今天&#xff0c;我们要学一下关于C语言里的能定位字符串中…