1. 程式人生 > >qt執行緒同步之條件等待

qt執行緒同步之條件等待

本文章使用QWaitCondition實現執行緒間的同步

#include <QApplication>
#include <QMutex>
#include <QThread>
#include <QSemaphore>
#include <QWaitCondition>
#include <iostream>
using namespace std;

// 需要生產的資料量
const int DATA_SIZE = 100;

// 指定緩衝區的大小
const int BUF_SIZE = 10;

// 存/取資料的緩衝區
int buf[BUF_SIZE] = {0};

QMutex mutex;// 實現執行緒間的互斥

// 當緩衝區沒有填充滿時,該條件被觸發(反之,當緩衝區被填充滿了,該條件會阻塞執行緒)
QWaitCondition bufIsNotFull;

// 當緩衝區不為空時,該條件被觸發(反之,當緩衝區為空時,該條件會阻塞執行緒)
QWaitCondition bufIsNotEmpty;

// 統計生產的且還沒有被消費的資料量
int nUsedSapce = 0;


class CProducer : public QThread
{
protected:
    virtual void run()
    {
        for (int i = 0 ; i < DATA_SIZE ; ++i)
        {
            mutex.lock();
            if (nUsedSapce == BUF_SIZE)// 如果緩衝區已填滿,則等待緩衝區中的資料被取走
                bufIsNotFull.wait(&mutex);// 在阻塞執行緒前,bufIsNotFull會解鎖互斥量,然後阻塞執行緒,等待bufIsNotFull條件物件被觸發,在返回前,會重新鎖定互斥量,然後返回

            buf[i%BUF_SIZE] = qrand() % 50 + 1;// 儲存生產的資料
            cout << "produce data is :" << buf[i%BUF_SIZE] << endl;

            ++nUsedSapce;// 生產了一個數據

            bufIsNotEmpty.wakeAll();// 喚醒所有等待bufIsNotEmpty條件的執行緒

            mutex.unlock();
        }
    }
};

class CConsumer : public QThread
{
protected:
    virtual void run()
    {
        for (int i = 0 ; i < DATA_SIZE ; ++i)
        {
            mutex.lock();
            if (nUsedSapce == 0)// 如果緩衝區為空,那麼等待緩衝區被填充資料
                bufIsNotEmpty.wait(&mutex);// 在阻塞執行緒前,bufIsNotEmpty會解鎖互斥量,然後阻塞執行緒,等待bufIsNotEmpty條件物件被觸發,在返回前,bufIsNotEmpty會重新鎖定互斥量,然後返回

            int nData = buf[i%BUF_SIZE];// 取出要消費的資料
            cout << "consume data is: " << nData << endl;

            --nUsedSapce;// 消費了一個數據

            bufIsNotFull.wakeAll();// 喚醒所有等待bufIsNotFull條件的執行緒

            mutex.unlock();
        }

    }
};


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

    CProducer producer;
    CConsumer consumer;

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

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

    return app.exec();
}