QWaitCondition Class

QWaitCondition 提供一个用于同步线程的条件变量. More...

头文件: #include <QWaitCondition>
qmake: QT += core

Note: All functions in this class are thread-safe.

公有函数

QWaitCondition()
~QWaitCondition()
void notify_all()
void notify_one()
bool wait(QMutex *lockedMutex, QDeadlineTimer deadline = QDeadlineTimer(QDeadlineTimer::Forever))
bool wait(QMutex *lockedMutex, unsigned long time)
bool wait(QReadWriteLock *lockedReadWriteLock, QDeadlineTimer deadline = QDeadlineTimer(QDeadlineTimer::Forever))
bool wait(QReadWriteLock *lockedReadWriteLock, unsigned long time)
void wakeAll()
void wakeOne()

详细描述

QWaitCondition 允许线程告诉其他线程某种条件已经满足. 一个或多个线程可以被阻塞并等待 QWaitCondition 使用 wakeOne() 或 wakeAll() 设置条件. 使用 wakeOne() 唤醒一个随机选择的线程, 或使用 wakeAll() 唤醒所有线程.

例如, 假设我们有三个任务, 当用户按下一个键时, 应该执行某些任务. 每个任务可以分成一个线程, 每个线程都有一个 run() 主体, 如下所示:

 forever {
     mutex.lock();
     keyPressed.wait(&mutex);
     do_something();
     mutex.unlock();
 }

这里, keyPressed 变量是 QWaitCondition 类型的全局变量.

第四个线程将读取按键, 并在每次收到按键时唤醒其他三个线程, 如下所示:

 forever {
     getchar();
     keyPressed.wakeAll();
 }

唤醒三个线程的顺序是未知的. 另外, 如果某些线程在按下键时仍在 do_something() 中, 它们将不会被唤醒 (因为它们没有等待条件变量), 因此该按键不会执行任务. 这个问题可以通过使用定时器和 QMutex 来解决. 例如, 下面是工作线程的新代码:

 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();
 }

互斥量是必需的, 因为当两个线程同时更改同一变量的值时, 结果是不可预测的.

等待条件是一个强大的线程同步原语. Wait Conditions Example 演示了如何使用 QWaitCondition 作为 QSemaphore 的替代品, 来控制生产者消费者的共享循环缓冲区的访问.

另见 QMutex, QSemaphore, QThread, Wait Conditions Example.

Member Function Documentation

QWaitCondition::QWaitCondition()

Constructs a new wait condition object.

QWaitCondition::~QWaitCondition()

Destroys the wait condition object.

void QWaitCondition::notify_all()

This function is provided for STL compatibility. It is equivalent to wakeAll().

This function was introduced in Qt 5.8.

void QWaitCondition::notify_one()

This function is provided for STL compatibility. It is equivalent to wakeOne().

This function was introduced in Qt 5.8.

bool QWaitCondition::wait(QMutex *lockedMutex, QDeadlineTimer deadline = QDeadlineTimer(QDeadlineTimer::Forever))

Releases the lockedMutex and waits on the wait condition. The lockedMutex must be initially locked by the calling thread. If lockedMutex is not in a locked state, the behavior is undefined. If lockedMutex is a recursive mutex, this function returns immediately. The lockedMutex will be unlocked, and the calling thread will block until either of these conditions is met:

  • Another thread signals it using wakeOne() or wakeAll(). This function will return true in this case.
  • the deadline given by deadline is reached. If deadline is QDeadlineTimer::Forever (the default), then the wait will never timeout (the event must be signalled). This function will return false if the wait timed out.

The lockedMutex will be returned to the same locked state. This function is provided to allow the atomic transition from the locked state to the wait state.

This function was introduced in Qt 5.12.

See also wakeOne() and wakeAll().

bool QWaitCondition::wait(QMutex *lockedMutex, unsigned long time)

This is an overloaded function.

bool QWaitCondition::wait(QReadWriteLock *lockedReadWriteLock, QDeadlineTimer deadline = QDeadlineTimer(QDeadlineTimer::Forever))

Releases the lockedReadWriteLock and waits on the wait condition. The lockedReadWriteLock must be initially locked by the calling thread. If lockedReadWriteLock is not in a locked state, this function returns immediately. The lockedReadWriteLock must not be locked recursively, otherwise this function will not release the lock properly. The lockedReadWriteLock will be unlocked, and the calling thread will block until either of these conditions is met:

  • Another thread signals it using wakeOne() or wakeAll(). This function will return true in this case.
  • the deadline given by deadline is reached. If deadline is QDeadlineTimer::Forever (the default), then the wait will never timeout (the event must be signalled). This function will return false if the wait timed out.

The lockedReadWriteLock will be returned to the same locked state. This function is provided to allow the atomic transition from the locked state to the wait state.

This function was introduced in Qt 5.12.

See also wakeOne() and wakeAll().

bool QWaitCondition::wait(QReadWriteLock *lockedReadWriteLock, unsigned long time)

This is an overloaded function.

void QWaitCondition::wakeAll()

Wakes all threads waiting on the wait condition. The order in which the threads are woken up depends on the operating system's scheduling policies and cannot be controlled or predicted.

See also wakeOne().

void QWaitCondition::wakeOne()

Wakes one thread waiting on the wait condition. The thread that is woken up depends on the operating system's scheduling policies, and cannot be controlled or predicted.

If you want to wake up a specific thread, the solution is typically to use different wait conditions and have different threads wait on different conditions.

See also wakeAll().