QT多线程
目录
QT多线程
一、多线程概念
继承QThread类
核心步骤 :
定义子类继承
QThread
,重写
run()
函数实现线程逻辑 。
#ifndef IOSTHREAD_H
#define IOSTHREAD_H
//保证能进行中文显示,QT对于中文有些不兼容
#if defined(_MSC_VER) && (_MSC_VER >= 1600)
# pragma execution_character_set("utf-8")
#endif
#include <QObject>
#include <QThread>
class IOSThread : public QThread
{
Q_OBJECT
public:
explicit IOSThread(QObject *parent = nullptr);
protected:
void run();
private:
};
#endif
#include "Threads/IOSThread.h"
#include "alldata.h"
IOSThread::IOSThread(QObject *parent)
: QThread(parent)
{
}
void IOSThread::run()
{
while(1)
{
QThread::msleep(1);
}
}
通过
start()
启动线程,
quit()
和
wait()
安全终止线程 。
//Threads
IOSThread *iosthread;
qDebug()<<"iosthread 开启线程";
iosthread = new IOSThread(this);
// 设置为最高优先级
iosthread->start();
iosthread->setPriority(QThread::TimeCriticalPriority);
线程优先级
优先级常量 | 数值 | 描述 | 应用场景 |
---|---|---|---|
QThread::IdlePriority | 0 | 空闲优先级 :仅在无其他线程运行时才调度。 | 后台监控、低优先级日志记录等 |
QThread::LowestPriority | 1 | 最低优先级 :调度频率低于 LowPriority 。 | 非关键性后台任务 |
QThread::LowPriority | 2 | 低优先级 :调度频率低于 NormalPriority 。 | 资源占用较低的任务(如数据备份) |
QThread::NormalPriority | 3 | 正常优先级 :操作系统的默认优先级。 | 普通用户交互任务 |
QThread::HighPriority | 4 | 高优先级 :调度频率高于 NormalPriority 。 | 实时数据处理或关键业务逻辑 |
QThread::HighestPriority | 5 | 最高优先级 :调度频率高于 HighPriority 。 | 高响应要求的任务(如传感器采集) |
QThread::TimeCriticalPriority | 6 | 时间关键优先级 :尽可能频繁调度,接近实时系统的优先级。 | 运动控制、高频信号处理等 |
QThread::InheritPriority | 7 | 继承优先级 :使用创建线程的优先级(默认值)。 | 需要与父线程优先级一致的任务 |
QThread::TimeCriticalPriority的优先级最高
QThread 类提供的延时函数
QThread::sleep(n)
:阻塞当前线程
n
秒
。
QThread::msleep(n)
:阻塞当前线程
n
毫秒
QThread::usleep(n)
:阻塞当前线程
n
微秒
示例:子线程执行耗时任务(如循环计算),通过信号通知主线程更新UI 。
特点 :
- 直接控制线程生命周期,但需注意
run()
函数外部的成员函数默认运行在主线程 - 适用于需要独立线程完成完整任务的场景(如硬件控制)
二、 线程同步与通信机制
全局互斥锁(QMutex\QMutexLocker)
对于需要全局动作的资源,如在线程中对数据库的增删改查,全局变量(生产数据、板卡、某些必要条件变量等)。
#include <QMutex>
#include <QDebug>
QMutex mutex; // 全局互斥锁
int shared_counter = 0;
void qt_increment_counter() {
mutex.lock();
shared_counter++;
qDebug() << "Counter:" << shared_counter;
mutex.unlock();
}
void qt_safe_increment_counter() {
QMutexLocker locker(&mutex); // 构造时加锁,析构时解锁
shared_counter++;
qDebug() << "Counter:" << shared_counter;
}
意事项
- 死锁风险
:避免嵌套加锁或忘记解锁,优先使用
lock_guard
/QMutexLocker
。 - 锁粒度 :尽量缩小临界区范围(如不在锁内执行耗时操作)
全局互斥锁(QMutex\QMutexLocker)
Qt的读写锁(
QReadWriteLock
)是一种线程同步机制,旨在优化多线程环境下对共享资源的访问效率。其核心原则为:
- 读共享
:允许多个线程同时获取读锁(
lockForRead()
),执行只读操作,互不干扰 。 - 写独占
:同一时间仅允许一个线程获取写锁(
lockForWrite()
),执行写入操作,期间阻塞其他所有读写操作 。 - 写优先策略 :默认情况下,写锁请求优先于读锁请求,确保写操作不会被无限延迟
锁操作函数
- 读锁
:
lockForRead()
阻塞直到获取读锁;tryLockForRead()
非阻塞尝试获取读锁,可设置超时 。 - 写锁
:
lockForWrite()
阻塞直到获取写锁;tryLockForWrite()
非阻塞尝试获取写锁 。 - 解锁
:
unlock()
释放当前持有的读锁或写锁
// 全局缓冲区和读写锁
QVector<int> buffer;
QReadWriteLock rwLock;
// 数据采集线程(写操作)
void dataAcquisitionThread() {
QWriteLocker locker(&rwLock);
buffer.append(newData); // 写入新数据
}
// 数据显示线程(读操作)
void dataDisplayThread() {
QReadLocker locker(&rwLock);
for (int val : buffer) qDebug() << val; // 读取数据
}
#include <QReadWriteLock>
#include <QThread>
#include <QDebug>
QReadWriteLock rwLock; // 全局读写锁
int sharedData = 0; // 共享资源
class ReaderThread : public QThread {
protected:
void run() override {
rwLock.lockForRead(); // 手动加读锁
qDebug() << "Read data:" << sharedData;
rwLock.unlock(); // 必须手动解锁!
}
};
class WriterThread : public QThread {
protected:
void run() override {
rwLock.lockForWrite(); // 手动加写锁
sharedData++;
qDebug() << "Write data:" << sharedData;
rwLock.unlock(); // 必须手动解锁!
}
};
注意事项 即使是读写锁,在使用过程中也要注意读锁进行锁后,也需要释放,在调用写锁,不然可能也会出现死锁的情况,同时解锁的时候可以尝试try,保证线程的安全释放锁资源。
void run() {
rwLock.lockForRead();
try {
// 临界区操作
} catch (...) {
rwLock.unlock();
throw;
}
rwLock.unlock();
}
rwLock.lockForRead();
// 读操作
rwLock.unlock();
rwLock.lockForWrite();
// 写操作
rwLock.unlock();