QWaiCondition的使用

QWaitCondition介绍

QWaitCondition 是一个 Qt 框架提供的等待条件类,用于多个线程之间的同步。通常和互斥锁(QMutex)或读写锁(QReadWriteLock)一起使用。

QWaitCondition 可以让线程在某个条件成立时等待,直到其他线程发出信号后唤醒它们。例如,在一个生产者消费者模型中,当队列已满时,生产线程需要等待;当队列为空时,消费线程也需要等待。

与 QMutex 或 QReadWriteLock 不同,QWaitCondition 并不会完成实际的锁定操作,而是提供了 wait() 方法来保持当前线程的休眠状态,并重新将线程加入线程调度器中。当其他线程改变了条件以后,通过 wakeOne() 或 wakeAll() 信号激活等待线程。

QWaitCondition主要特点在于其针对条件变量(condition variable)做优化,这使得性能更高,且适合跨平台应用。在使用上,QWaitCondition 主要配合互斥锁使用,互斥锁用于保证条件判断的原子性,等待的线程在进入等待前会释放锁,从而避免了死锁的问题。

代码示例

#ifndef DATAMANAGER_H
#define DATAMANAGER_H

#include <QDebug>
#include <QThread>
#include <QMutex>
#include <QWaitCondition>

class Data {
public:
    Data() : m_num(0), m_max(100) {}
    void produce(){
        QMutexLocker locker(&m_mutex);
        while(m_num > m_max){
            qDebug() << "Queue is full, wait for consumer to take products";
            m_notFull.wait(&m_mutex);
        }
        m_num++;
        qDebug() << "Produce a product, num = " << m_num;
        if(m_num > 0){
            m_notEmpty.wakeOne();
        }
    }

    void consume(){
        QMutexLocker locker(&m_mutex);
        while(m_num <= 0){
            qDebug() << "Queue is empty, wait for producer to produce products";
            m_notEmpty.wait(&m_mutex);
        }
        m_num--;
        qDebug() << "Consume a product, num = " << m_num;
        if(m_num < m_max){
            m_notFull.wakeOne();
        }
    }

private:
    QMutex m_mutex;
    QWaitCondition m_notEmpty;
    QWaitCondition m_notFull;
    int m_num;
    int m_max;
};

#endif // DATAMANAGER_H

在上述代码中,我们定义了一个 Data 类,该类表示一个共享的数据队列。在 produce() 和 consume() 方法中,我们使用了 wait()、wakeOne() 激活和唤醒所有等待的线程,通过 QMutex 来保证互斥锁在判断 num 的值时不会被其他线程修改,从而确保了多线程安全。

#ifndef THREADMANAGER_H
#define THREADMANAGER_H

#include <QDebug>
#include <QThread>
#include <QMutex>
#include <QWaitCondition>
#include "datamanager.h"

class Producer : public QThread {
    Q_OBJECT
public:
    Producer(Data *data): m_data(data){}
    void run() override {
        while(true)
        {
            m_data->produce();
            msleep(500);
        }

    }
private:
    Data *m_data;
};


class Consumer : public QThread {
    Q_OBJECT
public:
    Consumer(Data *data): m_data(data){}
    void run() override {
        while(true)
        {
            m_data->consume();
            msleep(1000);
        }
    }
private:
    Data *m_data;
};

#endif // THREADMANAGER_H
#include <QCoreApplication>
#include "datamanager.h"
#include "threadmanager.h"

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

    Data data;
    Producer producer(&data);
    Consumer consumer(&data);

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

    producer.wait();
    consumer.wait();

    return app.exec();
}

我们创建了 Producer 对象和 Consumer 对象,用于循环执行 produce() 和 consume() 方法,并启动这两个对象的线程来模拟生产者和消费者在不同的线程中同时运行的情况。

由于生产的速度比消费的速度快,程序的输出最终会稳定在如下的状态。可以通过调整生产和消费的时间,改变输出结果。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zw_ggr_2017

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值