【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交替搶佔的情況