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