QWaitCondition的使用

本文介绍了如何在Qt中使用QWaitCondition进行线程间的同步,展示了QThreadProducer和QThreadConsumer如何通过newdateAvaiable信号槽机制实现数据的生产与消费。QThreadProducer定时生成数据并唤醒消费者,而消费者在接收到信号后继续执行。

QWaitCondition 类

QWaitCondition 用于多线程的同步,一个线程调用QWaitCondition::wait() 阻塞等待,直到另一个线程调用QWaitCondition::wake() 唤醒才继续往下执行。

#include "qmythread.h"
#include <QWaitCondition>
#include <QTime>
#include <QMutex>

QMutex mutex;
QWaitCondition newdateAvaiable;
int seq=0;
int diceValue=0;

QThreadProducer::QThreadProducer()
{

}

void QThreadProducer::stopThread()
{
    QMutexLocker locker(&mutex);//在locker的生存周期内下面的程序是受保护的;
    m_stop=true;
}

void QThreadProducer::run()
{
    m_stop=false;
    seq=0;
    qsrand(QTime::currentTime().msec());

    while (!m_stop) {
        mutex.lock();
        diceValue=qrand();
        diceValue=(diceValue%6)+1;
        seq++;
        mutex.unlock();

        //唤醒所有线程
        newdateAvaiable.wakeAll();
        msleep(500);//线程休眠500毫秒

    }
}

QThreadConsumer::QThreadConsumer()
{

}

void QThreadConsumer::stopThread()
{
    QMutexLocker locker(&mutex);
    m_stop=true;
}

void QThreadConsumer::run()
{
    m_stop=false;
    while (!m_stop)
    {
        mutex.lock();
        /*QWaitCondition 用于多线程的同步,一个线程调用QWaitCondition::wait() 阻塞等待,
         * 直到另一个线程调用QWaitCondition::wake() 唤醒才继续往下执行。*/
        newdateAvaiable.wait(&mutex);//先解锁mutex,是其他线程能够使用mutex
        emit newValue(seq,diceValue);
        mutex.unlock();
    }
}

其中:QThreadProducer::run()函数负责产生数据(每隔500ms产生一个数据),新的数据产生后通过等待条件唤醒所有等待的线程,即:
通过newdataAvailiable.allWake()唤醒所有等待线程;
QthreadConsumer::run()函数中的while循环,首先需要将互斥量锁定,再执行下面的语句:newdataAvailable.wait(&mutex);
newdataAvailable.wait(&mutex);中以mutex作为输入参数,内部首先会解锁mutex,是其他线程可以使用mutex.newdataAvailable进入等待状态。当QThreadProducer产生数据使用newdataAvailable.wakeAll()唤醒所有线程,newdataAvailable.wait(&metuex)会再次锁定mutex,然后退出阻塞状态,以执行后面的语句;

所以,当两个线程同时运行时,即.started()后,均开始执行.run(), 由于 QthreadConsumer通过newdataAvailable.wait(&mutex);处于等待状态,不占用mutex所以QThreadProducer::run()可以顺利执行,直到解除mutex``,通过``newdataAvailable.wakeAll()唤醒处于休眠的QthreadConsumer线程。此时QthreadConsumer会再次锁定mutex,然后退出阻塞状态,以执行后面的语句;

<think>我们被要求解释QWaitCondition使用方法并提供示例代码。根据引用内容,QWaitCondition是用于多线程同步的类,通常与QMutex配合使用。它允许线程在某些条件不满足时等待,直到其他线程通过wakeOne()或wakeAll()将其唤醒。 核心方法: - wait(QMutex *mutex): 释放mutex并阻塞等待,直到被唤醒。唤醒后重新获取mutex。 - wakeOne(): 唤醒一个等待的线程(随机选择) - wakeAll(): 唤醒所有等待的线程 使用步骤: 1. 创建一个QMutex和一个QWaitCondition对象。 2. 在等待线程中: a. 锁定互斥锁(QMutexLocker) b. 检查条件是否满足,如果不满足则调用wait()等待(注意:wait会释放互斥锁,并在返回前重新获取) 3. 在其他线程中(改变条件后): a. 锁定互斥锁 b. 改变条件 c. 调用wakeOne()或wakeAll()唤醒等待的线程 d. 解锁互斥锁(通常由QMutexLocker在作用域结束时自动解锁) 经典场景:生产者-消费者模型 示例:生产者线程生成数据,消费者线程消费数据。当没有数据时,消费者等待;当生产者生产了数据后,唤醒消费者。 下面是一个简单的生产者-消费者模型的示例代码:</think>### Qt中QWaitCondition使用方法及示例代码 `QWaitCondition`是Qt中用于多线程同步的核心类,它允许线程在特定条件满足前进入等待状态,并在条件满足后被其他线程唤醒。以下是详细使用方法及示例: #### 🔑 核心机制 1. **协作模型**:需配合`QMutex`或`QReadWriteLock`使用,确保线程安全 2. **等待条件**:线程调用`wait()`释放锁并进入阻塞状态 3. **唤醒机制**:其他线程满足条件后调用`wakeOne()`或`wakeAll()` 4. **条件检查**:等待线程被唤醒后需重新检查条件(存在伪唤醒可能)[^1][^4] #### 📝 常用方法 ```cpp // 基本等待(配合QMutex) void wait(QMutex *mutex); // 带超时等待(单位:毫秒) bool wait(QMutex *mutex, unsigned long time); // 唤醒单个等待线程 void wakeOne(); // 唤醒所有等待线程 void wakeAll(); ``` #### 🧩 生产者-消费者模型示例 ```cpp #include <QWaitCondition> #include <QMutex> #include <QThread> #include <QDebug> const int BUFFER_SIZE = 5; int buffer[BUFFER_SIZE]; int usedSlots = 0; QMutex mutex; QWaitCondition bufferNotFull; // 缓冲区未满条件 QWaitCondition bufferNotEmpty; // 缓冲区非空条件 // 生产者线程 class Producer : public QThread { public: void run() override { for (int i = 0; i < 20; ++i) { mutex.lock(); // 缓冲区满时等待 while (usedSlots == BUFFER_SIZE) { qDebug() << "缓冲区满,生产者等待"; bufferNotFull.wait(&mutex); } // 生产数据 buffer[usedSlots++] = i; qDebug() << "生产数据:" << i << "| 缓冲区大小:" << usedSlots; // 唤醒消费者 if (usedSlots == 1) { bufferNotEmpty.wakeAll(); } mutex.unlock(); msleep(100); // 模拟生产耗时 } } }; // 消费者线程 class Consumer : public QThread { public: void run() override { for (int i = 0; i < 20; ++i) { mutex.lock(); // 缓冲区空时等待 while (usedSlots == 0) { qDebug() << "缓冲区空,消费者等待"; bufferNotEmpty.wait(&mutex); } // 消费数据 int data = buffer[--usedSlots]; qDebug() << "消费数据:" << data << "| 缓冲区大小:" << usedSlots; // 唤醒生产者 if (usedSlots == BUFFER_SIZE - 1) { bufferNotFull.wakeOne(); } mutex.unlock(); msleep(150); // 模拟消费耗时 } } }; int main() { Producer producer; Consumer consumer; producer.start(); consumer.start(); producer.wait(); consumer.wait(); return 0; } ``` #### ⚠️ 关键注意事项 1. **始终检查条件循环**:使用`while`而非`if`检查条件,防止伪唤醒[^1] ```cpp while (!condition) { waitCondition.wait(&mutex); } ``` 2. **锁管理**:`wait()`调用会**自动释放**关联的锁,返回时**重新获取**锁[^5] 3. **唤醒策略**: - `wakeOne()`:唤醒单个线程(随机选择),适用于单任务场景 - `wakeAll()`:唤醒所有等待线程,适用于多任务或资源争用场景 4. **超时处理**:带超时的`wait()`返回`bool`值,需检查超时状态: ```cpp if (!waitCondition.wait(&mutex, 5000)) { qDebug() << "等待超时!"; } ``` #### 💡 典型应用场景 1. 任务队列调度(线程池) 2. 资源池管理(数据库连接池) 3. 事件驱动的生产者-消费者模型 4. 多阶段流水线处理 5. 线程屏障同步 > **注意**:在Windows平台,每个`QWaitCondition`对象会创建手动重置事件对象(`CreateEvent`)[^2],需注意系统资源管理。 --- ### 相关问题 1. `QWaitCondition`与`QSemaphore`在同步机制上有哪些本质区别?[^3] 2. 如何处理`QWaitCondition`的伪唤醒(spurious wakeup)问题? 3. 在多生产者-多消费者模型中,如何优化`QWaitCondition`的使用性能? 4. `QWaitCondition::wait()`的毫秒级超时精度如何保证? 5. 在Qt的跨平台设计中,不同操作系统下`QWaitCondition`的实现有何差异?[^2] [^1]: QWaitCondition核心机制说明 [^2]: Windows平台实现细节 [^3]: 与其他同步工具对比 [^4]: 基本工作原理 [^5]: 关键方法行为说明
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值