QWaitCondition提供一个条件变量来实现线程间同步。
QWaitConditions允许一个线程告诉其它线程某种条件已经满足,一个或多个线程可以等待一个由wakeOne()或wakeAll()设定的条件QWaitCondition。使用wakeOne()会唤醒一种随机选择的事件或者wakeAll()会把它们全部唤醒。
比如,假定每次用户按下一个键,我们有三个任务要同时执行,每个任务都可以放到一个线程中,每个线程的run()都应该是这样:
forever {
mutex.lock();
keyPressed.wait(&mutex);
do_something();
mutex.unlock();
}
这里,,keyPressed变量是个全局的QWaitCondition.类型变量。
第四个线程应该读按键,每当它收到一个按键就唤醒其他三个线程,它应该像这样:
forever {
getchar();
keyPressed.wakeAll();
}
注意这三个线程被唤醒的顺序是未定义的,并且当键被按下时,这些线程中的一个或多个还在do_something(),它们将不会被唤醒(因为它们现在没有等待条件变量)并且这个任务也就不会针对这次按键执行操作。这种情况是可以通过使用一个计数器和互斥量来避免,比如,修改后的线程代码如下:
forever {
mutex.lock();
keyPressed.wait(&mutex);
++count;
mutex.unlock();
do_something();
mutex.lock();
--count;
mutex.unlock();
}
这是第四个线程的代码:
forever {
getchar();
mutex.lock();
// Sleep until there are no busy worker threads
while (count > 0) {
mutex.unlock();
sleep(1);
mutex.lock();
}
keyPressed.wakeAll();
mutex.unlock();
}
互斥量是必须的,因为两个线程试图同时对同一个变量进行修改的结果是不可预知的。
等待条件是一个有用的线程同步方法。等待条件的例子展示了如何运用QWaitCondition代替QSemaphore来实现操作环形缓冲区。消费者和生产者共享环形缓冲区。
请参考 QMutex, QSemaphore, QThread, and Wait Conditions Example.
成员函数说明
QWaitCondition::QWaitCondition ()
创建一个新的等待条件对象
QWaitCondition::~QWaitCondition ()
销毁一个等待条件对象
bool QWaitCondition::wait ( QMutex * mutex, unsigned long time = ULONG_MAX )
释放锁定的mutex并且在线程事件对象上等待。mutex必须由调用线程初始锁定的。如果mutex没有在锁定状态,这个函数立即返回。如果mutex是一个递归互斥量,这个函数立即返回。mutex将被解锁,并且调用线程将会阻塞,直到下列条件之一满足时才醒来:
另一个线程使用wakeOne()或wakeAll()传输信号给它。在这种情况下,函数将返回真。
time毫秒过去了。如果time为ULONG_MAX(默认值),那么这个等待将永远不会超时(这个事件必须被传输)。如果等待的事件超时,这个函数将会返回假。
互斥量将以同样的锁定状态返回。这个函数提供的是允许从锁定状态到等待状态的原子转换。
请参考 wakeOne() and wakeAll().
bool QWaitCondition::wait ( QReadWriteLock * readWriteLock, unsigned long time = ULONG_MAX )
释放锁定的readWriteLock并且在线程事件对象上等待。readWriteLock必须由调用线程初始锁定的。如果readWriteLock没有在锁定状态,这个函数立即返回。如果readWriteLock是一个递归互斥量,这个函数立即返回。readWriteLock将被解锁,并且调用线程将会阻塞,直到下列条件之一满足时才醒来:
另一个线程使用wakeOne()或wakeAll()传输信号给它。在这种情况下,这个函数将返回真。
time毫秒过去了。如果time为ULONG_MAX(默认值),那么这个等待将永远不会超时(这个事件必须被传输)。如果等待的事件超时,这个函数将会返回假。
互斥量将以同样的锁定状态返回。这个函数提供的是允许从锁定状态到等待状态的原子转换。
Qt 4.4 引进了该函数
请参考 wakeOne() and wakeAll().
void QWaitCondition::wakeAll ()
这将会唤醒所有等待QWaitCondition的线程。这些线程被唤醒的顺序依赖于操组系统的调度策略,并且不能被控制或预知。
请参考 wakeOne().
void QWaitCondition::wakeOne ()
这将唤醒某个等待QWaitCondition的线程。具体是那个线程被唤醒取决于操作系统的调度策略,并且不能被控制或预知。
如果想唤醒某个指定的线程,一般的办法是定义不同的等待条件QWaitCondition,让不同的线程等待不同的等待条件。
请参考 wakeAll()