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

QT-------------多线程

实现思路

  1. QThread 类简介
    • QThread 是 Qt 中用于多线程编程的基础类。可以通过继承 QThread 并重写 run() 方法来创建自定义的线程逻辑。
    • 新线程的执行从 run() 开始,调用 start() 方法启动线程。
  2. 掷骰子的多线程应用程序
    • 创建一个 DiceThread 类继承自 QThread,在 run() 方法中模拟掷骰子操作,并通过信号将结果发送出去。
  3. 线程同步
    • 线程同步的概念:确保多个线程之间协调操作,避免数据竞争和不一致性。
    • 基于互斥量的线程同步:使用 QMutex 确保在同一时间只有一个线程可以访问共享资源。
    • 基于读写锁的线程同步:使用 QReadWriteLock,允许多个读线程同时访问资源,但写线程独占资源。
    • 基于条件等待的线程同步:使用 QWaitConditionQMutex 结合,允许线程等待某个条件满足。
    • 基于信号量的线程同步:使用 QSemaphore 控制对资源的访问数量。

代码示例

1. QThread 类简介和掷骰子的多线程应用程序
#include <QtWidgets/QApplication>
#include <QtCore/QThread>
#include <QtCore/QRandomGenerator>
#include <QtCore/QDebug>
#include <QtCore/QMutex>
#include <QtCore/QReadWriteLock>
#include <QtCore/QWaitCondition>
#include <QtCore/QSemaphore>


class DiceThread : public QThread {
    Q_OBJECT
signals:
    void resultReady(int result);


protected:
    void run() override {
        while (!isInterruptionRequested()) {
            int diceValue = QRandomGenerator::global()->bounded(1, 7);
            emit resultReady(diceValue);
            msleep(1000);
        }
    }
};


int main(int argc, char *argv[]) {
    QApplication app(argc, argv);


    DiceThread diceThread;
    QObject::connect(&diceThread, &DiceThread::resultReady, [](int result) {
        qDebug() << "Dice result: " << result;
    });


    diceThread.start();


    // 运行一段时间后停止线程
    QThread::sleep(10);
    diceThread.requestInterruption();
    diceThread.wait();


    return app.exec();
}


#include "main.moc"
2. 基于互斥量的线程同步
#include <QtWidgets/QApplication>
#include <QtCore/QThread>
#include <QtCore/QRandomGenerator>
#include <QtCore/QDebug>
#include <QtCore/QMutex>


class SharedData {
public:
    int value = 0;
    QMutex mutex;
};


class IncrementThread : public QThread {
public:
    IncrementThread(SharedData *data) : data(data) {}


protected:
    void run() override {
        for (int i = 0; i < 1000; ++i) {
            data->mutex.lock();
            ++data->value;
            data->mutex.unlock();
            msleep(1);
        }
    }


private:
    SharedData *data;
};


int main(int argc, char *argv[]) {
    QApplication app(argc, argv);


    SharedData sharedData;


    IncrementThread thread1(&sharedData);
    IncrementThread thread2(&sharedData);


    thread1.start();
    thread2.start();


    thread1.wait();
    thread2.wait();


    qDebug() << "Final value: " << sharedData.value;


    return app.exec();
}


#include "main.moc"
3. 基于读写锁的线程同步
#include <QtWidgets/QApplication>
#include <QtCore/QThread>
#include <QtCore/QRandomGenerator>
#include <QtCore/QDebug>
#include <QtCore/QReadWriteLock>


class SharedData {
public:
    int value = 0;
    QReadWriteLock lock;
};


class ReadThread : public QThread {
public:
    ReadThread(SharedData *data) : data(data) {}


protected:
    void run() override {
        for (int i = 0; i < 1000; ++i) {
            data->lock.lockForRead();
            qDebug() << "Read value: " << data->value;
            data->lock.unlock();
            msleep(1);
        }
    }


private:
    SharedData *data;
};


class WriteThread : public QThread {
public:
    WriteThread(SharedData *data) : data(data) {}


protected:
    void run() override {
        for (int i = 0; i < 100; ++i) {
            data->lock.lockForWrite();
            ++data->value;
            data->lock.unlock();
            msleep(10);
        }
    }


private:
    SharedData *data;
};


int main(int argc, char *argv[]) {
    QApplication app(argc, argv);


    SharedData sharedData;


    ReadThread reader1(&sharedData);
    ReadThread reader2(&sharedData);
    WriteThread writer(&sharedData);


    reader1.start();
    reader2.start();
    writer.start();


    reader1.wait();
    reader2.wait();
    writer.wait();


    qDebug() << "Final value: " << sharedData.value;


    return app.exec();
}


#include "main.moc"

在这里插入图片描述

4. 基于条件等待的线程同步
#include <QtWidgets/QApplication>
#include <QtCore/QThread>
#include <QtCore/QRandomGenerator>
#include <QtCore/QDebug>
#include <QtCore/QMutex>
#include <QtCore/QWaitCondition>


class SharedData {
public:
    int value = 0;
    QMutex mutex;
    QWaitCondition condition;
    bool ready = false;
};


class ProducerThread : public QThread {
public:
    ProducerThread(SharedData *data) : data(data) {}


protected:
    void run() override {
        QRandomGenerator gen;
        for (int i = 0; i < 10; ++i) {
            QThread::msleep(1000);
            data->mutex.lock();
            data->value = gen.bounded(1, 100);
            data->ready = true;
            data->condition.wakeOne();
            data->mutex.unlock();
        }
    }


private:
    SharedData *data;
};


class ConsumerThread : public QThread {
public:
    ConsumerThread(SharedData *data) : data(data) {}


protected:
    void run() override {
        while (true) {
            data->mutex.lock();
            if (!data->ready) {
                data->condition.wait(&data->mutex);
            }
            qDebug() << "Consumed value: " << data->value;
            data->ready = false;
            data->mutex.unlock();
        }
    }


private:
    SharedData *data;
};


int main(int argc, char *argv[]) {
    QApplication app(argc, argv);


    SharedData sharedData;


    ProducerThread producer(&sharedData);
    ConsumerThread consumer(&sharedData);


    consumer.start();
    producer.start();


    return app.exec();
}


#include "main.moc"
5. 基于信号量的线程同步
#include <QtWidgets/QApplication>
#include <QtCore/QThread>
#include <QtCore/QRandomGenerator>
#include <QtCore/QDebug>
#include <QtCore/QSemaphore>


class SharedResource {
public:
    QSemaphore semaphore;


    void useResource() {
        semaphore.acquire();
        qDebug() << "Using resource...";
        QThread::msleep(100);
        semaphore.release();
    }
};


class UserThread : public QThread {
public:
    UserThread(SharedResource *resource) : resource(resource) {}


protected:
    void run() override {
        for (int i = 0; i < 10; ++i) {
            resource->useResource();
        }
    }


private:
    SharedResource *resource;
};


int main(int argc, char *argv[]) {
    QApplication app(argc, argv);


    SharedResource resource;
    resource.semaphore.release(3);


    UserThread thread1(&resource);
    UserThread thread2(&resource);
    UserThread thread3(&resource);


    thread1.start();
    thread2.start();
    thread3.start();


    thread1.wait();
    thread2.wait();
    thread3.wait();


    return app.exec();
}


#include "main.moc"

代码解释

1. QThread 类简介和掷骰子的多线程应用程序
  • DiceThread 类
    • 继承 QThread 并在 run() 中模拟掷骰子操作,使用 QRandomGenerator 生成 1 到 6 的随机数。
    • 通过 resultReady 信号将结果发送出去,在主线程中连接该信号并打印结果。
2. 基于互斥量的线程同步
  • SharedData 类
    • 包含一个 value 变量和 QMutex
  • IncrementThread 类
    • 每次循环对 value 加 1 前先加锁,加 1 后解锁,确保同一时间只有一个线程修改 value
3. 基于读写锁的线程同步
  • SharedData 类
    • 包含一个 value 变量和 QReadWriteLock
  • ReadThread 类
    • 读线程使用 lockForRead() 锁定,读取 value 后解锁。
  • WriteThread 类
    • 写线程使用 lockForWrite() 锁定,修改 value 后解锁,写线程独占资源,读线程可同时读。
4. 基于条件等待的线程同步
  • SharedData 类
    • 包含 valueQMutexQWaitConditionready 标志。
  • ProducerThread 类
    • 生产者线程生成数据,使用 wakeOne() 唤醒等待的消费者。
  • ConsumerThread 类
    • 消费者线程等待 ready 标志,使用 wait() 等待,一旦有数据可用,打印并重置 ready
5. 基于信号量的线程同步
  • SharedResource 类
    • 包含 QSemaphore,初始释放 3 个资源。
  • UserThread 类
    • 每次使用资源前先 acquire() 资源,使用后 release() 资源,确保最多 3 个线程同时使用资源。

使用说明

  • 对于每个示例,将代码保存为 main.cpp 文件。
  • 确保 .pro 文件包含 QT += core widgets 以及 CONFIG += c++11
  • 编译并运行程序,观察不同线程同步机制的效果。

在这里插入图片描述


http://www.kler.cn/a/465252.html

相关文章:

  • Java中如何实现线程安全的单例模式?
  • 基于物联网疫苗冷链物流监测系统设计
  • Elasticsearch:Lucene 2024 年回顾
  • C++语言编程————C++的输入与输出
  • 代码实战:基于InvSR对视频进行超分辨率重建
  • Linux系统在任意目录运行py脚本
  • checked 溢出问题
  • Javascript-web API-day04
  • canvas+fabric实现时间刻度尺(一)
  • 渗透Vulnhub-tr0ll靶机
  • 【开源社区openEuler实践】compass-ci
  • v-model响应式数据失效(能打印出来,但不渲染响应新数据)出现在异步操作或动态添加属性时赋值,使用 this.$set:
  • 比亚迪30亿教育慈善基金正式启动,助推中国科教进步
  • Go 如何优雅退出进程
  • mysql之组内排序ROW_NUMBER()函数
  • Agent系列:AppAgent v2-屏幕智能Agent(详解版)
  • Ajax数据爬取
  • 定制级安全重保方案,确保重大活动期间的网络安全无忧
  • Tailwind CSS:现代 CSS 框架的优雅之选
  • redis的集群模式与ELK基础
  • STM32传感器系列:GPS定位模块
  • 活动预告 |【Part1】Microsoft Azure 在线技术公开课:使用 Azure DevOps 和 GitHub 加速开发
  • spring中使用@Validated,什么是JSR 303数据校验,spring boot中怎么使用数据校验
  • 【行空板K10】MQTT服务器SIoT V2
  • LeetCode - 初级算法 数组(旋转数组)
  • Vue.js组件开发-如何动态设置下拉框数值