当前位置: 首页 > news >正文

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::IdlePriority0空闲优先级:仅在无其他线程运行时才调度。后台监控、低优先级日志记录等 
QThread::LowestPriority1最低优先级:调度频率低于 LowPriority非关键性后台任务 
QThread::LowPriority2低优先级:调度频率低于 NormalPriority资源占用较低的任务(如数据备份) 
QThread::NormalPriority3正常优先级:操作系统的默认优先级。普通用户交互任务 
QThread::HighPriority4高优先级:调度频率高于 NormalPriority实时数据处理或关键业务逻辑 
QThread::HighestPriority5最高优先级:调度频率高于 HighPriority高响应要求的任务(如传感器采集) 
QThread::TimeCriticalPriority6时间关键优先级:尽可能频繁调度,接近实时系统的优先级。运动控制、高频信号处理等 
QThread::InheritPriority7继承优先级:使用创建线程的优先级(默认值)。需要与父线程优先级一致的任务

  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;
}

意事项

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

全局互斥锁(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();

相关文章:

  • 初级网工之路: 如何通过服务器进行交换机的配置
  • Faster R-CNN原理详解以及Pytorch实现模型训练与推理
  • 【NexLM 开源系列】让 AI 聊天更丝滑:SSE 实现流式对话!
  • 存储过程和自定义函数在银行信贷业务中的应用(oracle)
  • pop_dialog_state(state: State)弹出对话栈并返回到主助手,让整个对话流程图可以明确追踪对话流,并将控制权委派给特定的子对话图。
  • CHI协议中的read transaction flow
  • UDP-网络编程/socket编程
  • 【K8s】专题十六(3):Kubernetes 包管理工具之 Helm 语法
  • Excel 中如何实现数据透视表?
  • 信奥赛CSP-J复赛集训(模拟算法专题)(9):P6437 [COCI 2011/2012 #6] JACK
  • 数据库系统概论(二)数据模型
  • 记录--有惊无险
  • 产城融合典范:树莓科技如何助力宜宾数字经济腾飞​
  • 自启动、关联启动的拦截规则
  • 4g串口发短信踩坑
  • 【文件系统】
  • C语言for循环语句的用法(非常详细)
  • Ubuntu 源码安装 Qt5
  • 报错E0513:不能将 “const wchar_t *“ 类型的值分配到 “LPWSTR“ (aka “wchar_t *“) 类型的实体
  • 【性能测试入门_01性能测试jmeter基础实操场景详解】
  • 梅花奖在上海|“我的乱弹我的团”,民营院团首次入围终评
  • 外交部就习近平主席将出席中拉论坛第四届部长级会议开幕式介绍情况
  • 前四月全国铁路完成固定资产投资1947亿元,同比增长5.3%
  • 体坛联播|穆勒主场完成拜仁谢幕战,山西车队再登环塔拉力赛
  • 新华时评:中国维护国际经贸秩序的立场坚定不移
  • 宇树科技王兴兴:第一桶金来自上海,欢迎上海的年轻人加入