QWaitCondition 提供了一個用於同步線程的條件變量。它允許一個線程後告訴其他的線程已經滿足了某種條件;一個或多個線程可以阻塞等待 QWaitCondition 來使用 wakeOne() 或 wakeAll() 設置條件。使用 wakeOne() 喚醒一個隨機選擇的線程或者 wakeAll() 喚醒全部等待的線程。
下面是 QWaitCondition 類中,常用的函數介紹:
bool wait (QMutex *lockedMutex, unsigned long time = ULONG_MAX)
釋放鎖資源等待等待條件。lockedMutex 初始化必須是上鎖的狀態,根據調用的線程。如果 lockedMutex 沒有上鎖,他的行爲是未知的。如果 lockedMutex 是可遞歸的鎖,則該函數立即返回。 lockedMutex 將被解鎖,調用線程將被阻塞,直到滿足以下任一條件:
- 另一個線程使用 wakeOne() 或 wakeAll() 發出信號。在這種情況下,這個函數將返回true 。
- 時間毫秒已經過去。如果時間是ULONG_MAX(默認值),那麼等待將永遠不會超時(必須通知事件)。如果等待超時,這個函數將返回 false 。
lockedMutex 將返回到相同 locked 狀態。此函數提供了允許原子性的從鎖定狀態轉換到等待狀態。。
void wakeOne () 和 void wakeAll ()
表示喚醒一個或多個線程。喚醒的順序是根據操作系統的調度決定的。
上一篇文章我們介紹了使用信號量實現 生產者-消費者 例子
線程的互斥和同步(6)- Qt的信號量QSemaphore
條件變量是一個針對信號量的可替代選擇,本篇文章將使用條件變量替代信號量,實現同樣的效果:
數據定義,頭文件:
#include <QSemaphore>
#include <QWaitCondition>
#include <QMutex>
#include <atomic>
extern "C" int g_data[20];
extern "C" int g_nStartIndex;
extern "C" int g_nEndIndex;
extern "C" int g_nCurrentCreated;
extern "C" QWaitCondition g_notFullCondition; // 未滿條件變量
extern "C" QWaitCondition g_notEmptyCondition; // 未空條件變量
extern "C" QMutex g_mutex;
cpp文件
int g_data[20] = {-1};
int g_nStartIndex = 0;
int g_nEndIndex = 0;
int g_nCurrentCreated = 0;
QWaitCondition g_notFullCondition;
QWaitCondition g_notEmptyCondition;
QMutex g_mutex;
生產者實現:
void ProducerThread::run(void)
{
while (1)
{
g_mutex.lock();
// 當緩存滿了的時候,等待是否有消費者消費
if (g_nCurrentCreated == 20)
g_notFullCondition.wait(&g_mutex);
g_mutex.unlock();
// 生產數據
g_data[g_nEndIndex] = number;
std::cout << "Created Data: " << number++ \
<< ", Index is " << g_nEndIndex << std::endl;
g_nEndIndex++;
if (g_nEndIndex == 20)
g_nEndIndex = 0;
::Sleep(100);
g_mutex.lock();
g_nCurrentCreated++;
// 喚醒消費者
g_notEmptyCondition.wakeAll();
g_mutex.unlock();
}
}
消費者實現:
void ConsumerThread::run(void)
{
while (1)
{
g_mutex.lock();
// 等待
if (g_nCurrentCreated == 0)
g_notEmptyCondition.wait(&g_mutex);
g_mutex.unlock();
// 消費數據
std::cout << "Read Value: " << g_data[g_nStartIndex] \
<< ", Index is " << g_nStartIndex << std::endl;
g_nStartIndex++;
if (g_nStartIndex == 20)
g_nStartIndex = 0;
::Sleep(2000);
// 釋放資源
g_mutex.lock();
g_nCurrentCreated--;
// 喚醒生產者生產
g_notFullCondition.wakeAll();
g_mutex.unlock();
}
}
程序運行結果:
Created Data: 0, Index is 0
Created Data: 1, Index is 1
Read Value: 0, Index is 0
Created Data: 2, Index is 2
Created Data: 3, Index is 3
Created Data: 4, Index is 4
Created Data: 5, Index is 5
Created Data: 6, Index is 6
Created Data: 7, Index is 7
Created Data: 8, Index is 8
Created Data: 9, Index is 9
Created Data: 10, Index is 10
Created Data: 11, Index is 11
Created Data: 12, Index is 12
Created Data: 13, Index is 13
Created Data: 14, Index is 14
Created Data: 15, Index is 15
Created Data: 16, Index is 16
Created Data: 17, Index is 17
Created Data: 18, Index is 18
Created Data: 19, Index is 19
Read Value: 1, Index is 1
Created Data: 20, Index is 0
Read Value: 2, Index is 2
Created Data: 21, Index is 1
Read Value: 3, Index is 3
Created Data: 22, Index is 2
Read Value: 4, Index is 4
Created Data: 23, Index is 3
…
作者:douzhq
個人博客主頁:不會飛的紙飛機
文章同步頁(可下載完整代碼):線程的互斥和同步(6)- Qt的條件變量QWaitCondition