QT多线程

一、多线程概念

继承QThread类

  • 核心步骤 :
    *
    定义子类继承QThread,重写run()函数实现线程逻辑 。

    cpp 复制代码
    #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
    cpp 复制代码
    #include "Threads/IOSThread.h"
    #include "alldata.h"
    
    IOSThread::IOSThread(QObject *parent)
        : QThread(parent)
    {
    
    }
    
    void IOSThread::run()
    {
        while(1)
        {
            QThread::msleep(1);
        }
    }
    • 通过start()启动线程,quit()和wait()安全终止线程 。

      cpp 复制代码
          //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)

对于需要全局动作的资源,如在线程中对数据库的增删改查,全局变量(生产数据、板卡、某些必要条件变量等)。

cpp 复制代码
#include <QMutex>
#include <QDebug>

QMutex mutex; // 全局互斥锁
int shared_counter = 0;

void qt_increment_counter() {
    mutex.lock();
    shared_counter++;
    qDebug() << "Counter:" << shared_counter;
    mutex.unlock();
}
cpp 复制代码
void qt_safe_increment_counter() {
    QMutexLocker locker(&mutex); // 构造时加锁,析构时解锁
    shared_counter++;
    qDebug() << "Counter:" << shared_counter;
}

意事项

  1. 死锁风险 :避免嵌套加锁或忘记解锁,优先使用lock_guard/QMutexLocker。
  2. 锁粒度:尽量缩小临界区范围(如不在锁内执行耗时操作)

全局互斥锁(QMutex\QMutexLocker)

Qt的读写锁(QReadWriteLock)是一种线程同步机制,旨在优化多线程环境下对共享资源的访问效率。其核心原则为:

  • 读共享 :允许多个线程同时获取读锁(lockForRead()),执行只读操作,互不干扰 。
  • 写独占 :同一时间仅允许一个线程获取写锁(lockForWrite()),执行写入操作,期间阻塞其他所有读写操作 。
  • 写优先策略:默认情况下,写锁请求优先于读锁请求,确保写操作不会被无限延迟

锁操作函数

  • 读锁 :lockForRead() 阻塞直到获取读锁;tryLockForRead() 非阻塞尝试获取读锁,可设置超时 。
  • 写锁 :lockForWrite() 阻塞直到获取写锁;tryLockForWrite() 非阻塞尝试获取写锁 。
  • 解锁 :unlock() 释放当前持有的读锁或写锁
cpp 复制代码
// 全局缓冲区和读写锁
QVector<int> buffer;
QReadWriteLock rwLock;

// 数据采集线程(写操作)
void dataAcquisitionThread() {
    QWriteLocker locker(&rwLock);
    buffer.append(newData); // 写入新数据
}

// 数据显示线程(读操作)
void dataDisplayThread() {
    QReadLocker locker(&rwLock);
    for (int val : buffer) qDebug() << val; // 读取数据
}
cpp 复制代码
#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,保证线程的安全释放锁资源。

cpp 复制代码
void run() {
    rwLock.lockForRead();
    try {
        // 临界区操作
    } catch (...) {
        rwLock.unlock();
        throw;
    }
    rwLock.unlock();
}
cpp 复制代码
rwLock.lockForRead();
// 读操作
rwLock.unlock();

rwLock.lockForWrite();
// 写操作
rwLock.unlock();
相关推荐
宿州派大星4 小时前
Python实战:PyQt5 + OpenCV + Dlib 打造AI桌面应用
人工智能·python·qt
长沙红胖子Qt13 小时前
Qt+TiePieHS3开发笔记(二):HS3发送器发出内置波形、直连示波器,示波器检测内置波形Demo
qt·示波器·tiepiehs3·发生器·同步发射和示波器采集
陈年老古董16 小时前
PyQt5 入门指南:环境搭建、PyCharm 外部工具配置与登录界面实战
开发语言·qt·pycharm
zhanghaha131417 小时前
Qt 类完整例程【逐词拆解 + 逐步骤执行保姆教程】
开发语言·qt
Cx330❀21 小时前
Qt 界面美化指南:从零掌握 QSS 核心机制与工程实践
开发语言·qt·ui·性能优化·图形渲染
zx_741484811 天前
PyQt5 环境搭建保姆级教程:PyCharm + QtDesigner + PyUIC 完整配置
开发语言·qt·pycharm·pyqt
Python图像识别1 天前
46-【2027毕设】YOLO11田间杂草检测识别系统 - Python完整源码+PyQt5界面+训练模型+数据集
python·qt·课程设计
沫璃染墨2 天前
《Qt从零入门系列(十三):QSS样式表详解——从选择器与层叠规则到控件美化实战》
开发语言·css·c++·qt·ui·qt6.3·qss
好好学习O(∩_∩)O2 天前
[QT] 多线程moveToThread 和易踩的8个坑
开发语言·qt
北i2 天前
Dubbo 默认超时重试:把下游打雪崩的隐形放大器
开发语言·qt·dubbo