1. 程式人生 > >【Qt多執行緒之執行緒的等待和喚醒】QWaitCondition

【Qt多執行緒之執行緒的等待和喚醒】QWaitCondition

QWatiCondition的成員函式

·QWaitCondition()    
·~QWaitCondition()  
·bool wait ( QMutex * mutex, unsigned long time = ULONG_MAX )
·void wakeOne ()
·void wakeAll ()

QWatiCondition::wait()

·bool wait ( QMutex * mutex, unsigned long time = ULONG_MAX )
引數:
(1)釋放鎖定的mutex
(2)阻塞的時間
功能:
mutex將被解鎖,並且呼叫執行緒將會阻塞,直到下列條件之一滿足才想來:
(1)另一個執行緒使用wakeOne()或wakeAll()傳輸給它;
(2)time毫秒過去。

wakeAll()

功能:喚醒所有等待的執行緒。

wakeOne()

功能:喚醒等待QWaitCondition的執行緒中的一個執行緒。

*注意:這裡我暫且還不能分清wakeAll()和wakeOne()的區別

例子1:消費者和生產者

要點:
(1)生產者必須檢查緩衝是否已滿(numUsedBytes == BufferSize),如果是,執行緒停下來等待bufferEmpty.wakeAll();如果不是,生產資料,增加numUsedBytes ,啟用numUsedBytes ==80

(2)當程式開始執行的時候,只有生產者可以執行。消費者被阻塞等待 bufferFull.wakeAll(); 一旦生產者在緩衝中放入一個位元組,消費者執行緒就被喚醒。

(3)鎖定狀態到等待狀態的轉換是原子操作。。。(第一次接觸到原子操作)

主要分為3個部分:
main.cpp,WatiCondition.h, WatiCondition.cpp

WatiCondition.h

#pragma once
#include <QThread>
#include <QtDebug>
#include <QMutex>
#include <QWaitCondition>

class Producer :
    public QThread
{
public:
    Producer();
    ~Producer();

    void
run(); }; class Comsumer : public QThread { public: Comsumer(); ~Comsumer(); void run(); };

WatiCondition.cpp

#include "WatiCondition.h"
#include <iostream>

QWaitCondition bufferEmpty;
QWaitCondition bufferFull;

QMutex mutex;

const int DataSize = 1000;
const int BufferSize = 80;
int buffer[BufferSize];

int numUsedBytes = 0;
int rIndex = 0;

Producer::Producer()
{

}

Producer::~Producer()
{

}

void Producer::run()
{
    for (int i = 0; i < DataSize; i++)
    {
        mutex.lock();
        if (numUsedBytes == BufferSize)
            bufferEmpty.wait(&mutex);   //容量已滿,生產者阻塞
        buffer[i%BufferSize] = i%BufferSize;
        numUsedBytes++;      //用來記錄當前緩衝區是否已滿
        bufferFull.wakeAll();        //緩衝區有容量,喚醒消費者
        mutex.unlock();
    }
}

Comsumer::Comsumer()
{

}

Comsumer::~Comsumer()
{

}

void Comsumer::run()
{
    for (int i = 0; i < DataSize; i++)
    {
        mutex.lock();
        if (numUsedBytes == 0)
            bufferFull.wait(&mutex);  //容量為空,阻塞消費者   
        qDebug() << currentThreadId() << buffer[i%BufferSize];
        numUsedBytes--;
        bufferEmpty.wakeAll();     //緩衝區未滿,喚醒生產者
        mutex.unlock();
    }
    std::cout << std::endl;
}

main.cpp

#include <QCoreApplication>
#include "WatiCondition.h"

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

    Producer producer;
    Comsumer consumerA;
    Comsumer consumerB;

    producer.start();
    consumerA.start();
    consumerB.start();

    producer.wait();
    consumerA.wait();
    consumerB.wait();

    return a.exec();
}

關於這個例項的一些疑惑?

這個例子中含有4個執行緒,主執行緒,生產者執行緒,消費者執行緒1,消費者執行緒2;
問題就是:生產者執行緒中的bufferEmpty.wakeAll()觸發,自動unlock()之後 ;互斥量處於需要被搶佔的情況,也就是消費者執行緒1和消費者執行緒2搶佔。那麼,會不會出現消費者執行緒1一直搶佔,而2搶佔不到的情況呢?
下面是我的程式執行圖
這裡寫圖片描述
發現一開始都被執行緒1搶佔,後面出現了執行緒1和2交替搶佔的情況