项目场景:
Qt中,线程通信无处不在,最核心的特性信号槽就是一种线程间通信,安全可靠易用。除此之外,还有别的几种常用的方式:
QMutex
互斥锁,可以保护共享的数据访问,例如对共享数据globalCounter得读写,可以保证数据的唯一和安全。
#include <QCoreApplication>
#include <QThread>
#include <QMutex>
#include <QDebug>QMutex mutex;
int globalCounter = 0;class Worker : public QThread {
protected:void run() override {for (int i = 0; i < 1000; ++i) {mutex.lock();++globalCounter;mutex.unlock();}}
};int main(int argc, char *argv[]) {QCoreApplication app(argc, argv);Worker worker1, worker2;worker1.start();worker2.start();worker1.wait();worker2.wait();qDebug() << "Global counter:" << globalCounter;return 0;
}
QWaitCondition:
条件等待通常与QMutex搭配使用,本质是等待某一线程释放mutex后,别的线程才可以使用,添加了事件执行条件,可以避免同一时间多个线程同时访问同一变量。
#include <QCoreApplication> #include <QThread> #include <QMutex> #include <QWaitCondition> #include <QDebug>QMutex mutex; QWaitCondition condition; bool ready = false;class Producer : public QThread { protected:void run() override {mutex.lock();qDebug() << "Producer is producing.";ready = true;condition.wakeOne();mutex.unlock();} };class Consumer : public QThread { protected:void run() override {mutex.lock();if (!ready) {condition.wait(&mutex);}qDebug() << "Consumer is consuming.";mutex.unlock();} };int main(int argc, char *argv[]) {QCoreApplication app(argc, argv);Producer producer;Consumer consumer;consumer.start();producer.start();consumer.wait();producer.wait();return 0; }
QSemaphore:
信号量可以控制访问特定资源的线程数量。
#include <QCoreApplication> #include <QThread> #include <QSemaphore> #include <QDebug>QSemaphore semaphore(3); // 允许同时访问资源的数量class Worker : public QThread { protected:void run() override {semaphore.acquire();qDebug() << "Worker is accessing resource in thread:" << QThread::currentThread();QThread::sleep(1); // 模拟工作semaphore.release();} };int main(int argc, char *argv[]) {QCoreApplication app(argc, argv);Worker workers[10];for (auto &worker : workers) {worker.start();}for (auto &worker : workers) {worker.wait();}return 0; }
QEvent:
使用事件队列传递和处理,实现线程间的通信。
#include <QCoreApplication>
#include <QThread>
#include <QDebug>
#include <QEvent>
#include <QApplication>class CustomEvent : public QEvent {
public:static const QEvent::Type EventType = static_cast<QEvent::Type>(QEvent::User + 1);CustomEvent(const QString &message) : QEvent(EventType), message(message) {}QString message;
};class EventReceiver : public QObject {
protected:bool event(QEvent *event) override {if (event->type() == CustomEvent::EventType) {CustomEvent *customEvent = static_cast<CustomEvent *>(event);qDebug() << "Received custom event with message:" << customEvent->message;return true;}return QObject::event(event);}
};class EventSender : public QThread {
protected:void run() override {QThread::sleep(1);qApp->postEvent(receiver, new CustomEvent("Hello from another thread!"));}
public:EventReceiver *receiver;
};int main(int argc, char *argv[]) {QCoreApplication app(argc, argv);EventReceiver receiver;EventSender sender;sender.receiver = &receiver;sender.start();sender.wait();return app.exec();
}