文章目錄
- 條件變量
- 使用 wakeOne()
- 使用 wakeAll()
條件變量
QT的條件變量類是QWaitCondition
,有wakeOne()
和 wakeAll()
兩個方法
wakeOne()
:僅喚醒一個等待的線程。wakeAll()
:喚醒所有等待的線程。
使用 wakeOne()
https://github.com/BinaryAI-1024/QtStudy/tree/master/thread/conditionVariable
有 3 個工作線程 在 QWaitCondition
上等待,wakeOne()
只喚醒其中一個線程。
// main.cpp
#include <QCoreApplication>
#include <QThread>
#include <QTimer>
#include "myworker.h"int main(int argc, char *argv[]) {QCoreApplication app(argc, argv);const int numThreads = 3;QThread* threads[numThreads];MyWorker* workers[numThreads];for (int i = 0; i < numThreads; ++i) {threads[i] = new QThread();workers[i] = new MyWorker();workers[i]->moveToThread(threads[i]);// 線程啟動時,工作對象執行 doWork()QObject::connect(threads[i], &QThread::started, workers[i], &MyWorker::doWork);// 任務完成后退出線程的事件循環QObject::connect(workers[i], &MyWorker::finished, threads[i], &QThread::quit);// 任務完成后刪除工作對象QObject::connect(workers[i], &MyWorker::finished, workers[i], &QObject::deleteLater);// 線程退出后刪除線程對象QObject::connect(threads[i], &QThread::finished, threads[i], &QObject::deleteLater);threads[i]->start();}// 2 秒后喚醒所有線程QTimer::singleShot(2000, [=]() {workers[0]->startWork(); // 讓所有 worker 線程醒來});return app.exec();
}
// myworker.h
#ifndef MYWORKER_H
#define MYWORKER_H#include <QObject>
#include <QThread>
#include <QMutex>
#include <QWaitCondition>
#include <QDebug>class MyWorker : public QObject {Q_OBJECT
public:explicit MyWorker(QObject *parent = nullptr);~MyWorker();
signals:void finished();
public slots:void doWork();void startWork();private:QMutex mutex; // 每個實例都有一個互斥鎖QWaitCondition condition; // 每個實例都有一個條件變量bool ready = false; // 每個實例都有一個標志變量
};#endif // MYWORKER_H
// myworker.cpp
#include "myworker.h"MyWorker::MyWorker(QObject *parent) : QObject(parent) {}MyWorker::~MyWorker() {qDebug() << QThread::currentThread() << "Worker destroyed";
}void MyWorker::doWork() {qDebug() << QThread::currentThread() << "Worker waiting...";{QMutexLocker locker(&mutex); // 加鎖while (!ready) { // 等待被喚醒condition.wait(&mutex);}}qDebug() << QThread::currentThread() << "Worker processing...";QThread::msleep(2000);qDebug() << QThread::currentThread() << "Worker finished!";emit finished();
}void MyWorker::startWork() {QMutexLocker locker(&mutex);ready = true;condition.wakeOne(); // 僅喚醒一個線程
}
運行結果
QThread(0x1481b00) Worker waiting...
QThread(0x1487b10) Worker waiting...
QThread(0x1487d58) Worker waiting...
QThread(0x1481b00) Worker processing...
QThread(0x1481b00) Worker finished!
QThread(0x1481b00) Worker destroyed
使用 wakeAll()
https://github.com/BinaryAI-1024/QtStudy/tree/master/thread/conditionVariableAll
有 3 個工作線程在 QWaitCondition
上等待,wakeAll()
同時喚醒所有線程。這需要將QMutex
、QWaitCondition
和 ready
聲明為靜態變量,在多個 MyWorker實例間共享。
// main.cpp
#include <QCoreApplication>
#include <QThread>
#include <QTimer>
#include "myworker.h"int main(int argc, char *argv[]) {QCoreApplication app(argc, argv);const int numThreads = 3;QThread* threads[numThreads];MyWorker* workers[numThreads];for (int i = 0; i < numThreads; ++i) {threads[i] = new QThread();workers[i] = new MyWorker();workers[i]->moveToThread(threads[i]);// 線程啟動時,工作對象執行 doWork()QObject::connect(threads[i], &QThread::started, workers[i], &MyWorker::doWork);// 任務完成后退出線程的事件循環QObject::connect(workers[i], &MyWorker::finished, threads[i], &QThread::quit);// 任務完成后刪除工作對象QObject::connect(workers[i], &MyWorker::finished, workers[i], &QObject::deleteLater);// 線程退出后刪除線程對象QObject::connect(threads[i], &QThread::finished, threads[i], &QObject::deleteLater);threads[i]->start();}// 2 秒后喚醒所有線程QTimer::singleShot(2000, [=]() {workers[0]->startWork(); // 讓所有 worker 線程醒來});return app.exec();
}
// myworker.h
#ifndef MYWORKER_H
#define MYWORKER_H#include <QObject>
#include <QThread>
#include <QMutex>
#include <QWaitCondition>
#include <QDebug>class MyWorker : public QObject {Q_OBJECT
public:explicit MyWorker(QObject *parent = nullptr);~MyWorker();
signals:void finished();
public slots:void doWork();void startWork();private:static QMutex mutex; // 互斥鎖(多個 MyWorker 共享)static QWaitCondition condition; // 等待條件(多個 MyWorker 共享)static bool ready; // 共享的標志變量
};#endif // MYWORKER_H
// myworker.cpp
#include "myworker.h"
#include <QMutexLocker>
// 共享變量初始化
QMutex MyWorker::mutex;
QWaitCondition MyWorker::condition;
bool MyWorker::ready = false;MyWorker::MyWorker(QObject *parent) : QObject(parent) {}MyWorker::~MyWorker() {qDebug() << QThread::currentThread() << "Worker destroyed";
}void MyWorker::doWork() {qDebug() << QThread::currentThread() << "Worker waiting...";{QMutexLocker locker(&mutex); // 加鎖while (!ready) { // 等待被喚醒condition.wait(&mutex);}}qDebug() << QThread::currentThread() << "Worker processing...";QThread::msleep(2000);qDebug() << QThread::currentThread() << "Worker finished!";emit finished();
}void MyWorker::startWork() {QMutexLocker locker(&mutex);ready = true;condition.wakeAll(); // 喚醒所有等待的線程
}
運行結果
QThread(0xa9f1b00) Worker waiting...
QThread(0xa9f7fd8) Worker waiting...
QThread(0xa9f80d0) Worker waiting...
QThread(0xa9f1b00) Worker processing...
QThread(0xa9f80d0) Worker processing...
QThread(0xa9f7fd8) Worker processing...
QThread(0xa9f1b00) Worker finished!
QThread(0xa9f80d0) Worker finished!
QThread(0xa9f7fd8) Worker finished!
QThread(0xa9f1b00) Worker destroyed
QThread(0xa9f7fd8) Worker destroyed
QThread(0xa9f80d0) Worker destroyed