QWaitCondition 类

QWaitCondition 类提供了一种用于同步线程的条件变量。《更多信息...》

头文件 #include <QWaitCondition>
CMakefind_package(Qt6 REQUIRED COMPONENTS Core)
target_link_libraries(mytarget PRIVATE Qt6::Core)
qmakeQT += core

注意:本类中所有函数均线程安全

公共函数

QWaitCondition()
~QWaitCondition()
voidnotify_all()
voidnotify_one()
boolwait(QMutex *lockedMutex, QDeadlineTimer deadline = QDeadlineTimer(QDeadlineTimer::Forever))
boolwait(QMutex *lockedMutex, unsigned long time)
boolwait(QReadWriteLock *lockedReadWriteLock, QDeadlineTimer deadline = QDeadlineTimer(QDeadlineTimer::Forever))
boolwait(QReadWriteLock *lockedReadWriteLock, unsigned long time)
voidwakeAll()
voidwakeOne()

详细说明

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

必须使用互斥锁,因为两个线程试图同时更改同一变量的结果是不可预测的。

等待条件是一种强大的线程同步原语。示例 生产者和消费者使用等待条件 展示了如何使用 QWaitCondition 作为 QSemaphore 的替代品来控制生产者线程和消费者线程共享的循环缓冲区的访问。

另请参阅 QMutexQSemaphoreQThread使用等待条件的生产者和消费者

成员函数文档

QWaitCondition::QWaitCondition()

构建一个新的等待条件对象。

[noexcept] QWaitCondition::~QWaitCondition()

销毁等待条件对象。

void QWaitCondition::notify_all()

此函数提供了 STL 兼容性。它与 wakeAll() 等价。

void QWaitCondition::notify_one()

此函数提供了 STL 兼容性。它与 wakeOne() 等价。

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

释放 lockedMutex 并在等待条件上等待。必须由调用线程首先锁定 lockedMutex。如果 lockedMutex 不处于锁定状态,行为是未定义的。如果 lockedMutex 是递归互斥锁,则此函数将立即返回。将解锁 lockedMutex,调用线程将阻塞,直到以下条件之一得到满足

  • 另一个线程使用 wakeOne() 或 wakeAll() 进行信号。在这种情况下,此函数将返回 true。
  • 给定 deadline 的截止日期。如果 deadlineQDeadlineTimer::Forever(默认值),则等待永远不会超时(事件必须被信号)。如果等待超时,此函数将返回 false。

lockedMutex 将返回到相同的锁定状态。此函数提供以允许从锁定状态到等待状态的原子转换。

另请参阅 wakeOne() 和 wakeAll

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

这是一个重载函数。

释放 lockedMutex 并在等待条件下等待 time 毫秒。

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

释放 lockedReadWriteLock 并在等待条件上等待。必须由调用线程首先锁定 lockedReadWriteLock。如果 lockedReadWriteLock 不处于锁定状态,则此函数将立即返回。如果递归锁定,则不释放锁,否则此函数将无法正确释放锁。调用线程将阻塞,直到以下条件之一得到满足

  • 另一个线程使用 wakeOne() 或 wakeAll() 进行信号。在这种情况下,此函数将返回 true。
  • 给定 deadline 的截止日期。如果 deadlineQDeadlineTimer::Forever(默认值),则等待永远不会超时(事件必须被信号)。如果等待超时,此函数将返回 false。

锁定读/写锁lockedReadWriteLock将会返回到相同的状态。此函数提供原子地从锁定状态转换为等待状态的机制。

另请参阅 wakeOne() 和 wakeAll

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

这是一个重载函数。

释放lockedReadWriteLock并等待time毫秒的等待条件。

void QWaitCondition::wakeAll()

唤醒所有等待在等待条件上的线程。唤醒线程的顺序取决于操作系统的调度策略,无法控制或预测。

另请参阅wakeOne()。

void QWaitCondition::wakeOne()

唤醒等待在等待条件上的一个线程。唤醒哪个线程取决于操作系统的调度策略,无法控制或预测。

如果你想要唤醒特定的线程,通常的方法是使用不同的等待条件,让不同的线程等待不同的条件。

另请参阅wakeAll

© 2024 Qt公司版权所有。本文件包含的文档贡献者各自拥有版权。提供的文档受自由软件基金会发布的GNU自由文档许可证第1.3版条款限制。Qt以及相关标志是芬兰的Qt公司和/或世界其他国家/地区的注册商标。所有其他商标均为其各自所有者的财产。