首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C >> 關於C

Qt 多線程程序設計全解析:線程類、同步機制、信號槽跨線程、隱式共享

     編輯:關於C

Qt 通過 QThread、同步原語、事件循環、信號槽機制提供完整的多線程支持。本文系統梳理:線程創建與運行、四大同步類、可重入與線程安全、QObject 線程親緣性、跨線程信號槽三種連接類型、事件循環、隱式共享線程安全性,附核心代碼模板與最佳實踐。

1. 核心線程相關類

2. 創建線程:兩種模式

模式 A:繼承 QThread 重寫 run()

class WorkerThread : public QThread {
    Q_OBJECT
protected:
    void run() override {
        // 線程入口,執行耗時任務
        for (int i=0; i<100; ++i) {
            // 工作...
            msleep(10);
        }
        emit finished();
    }
signals:
    void finished();
};

// 使用
WorkerThread *thread = new WorkerThread;
connect(thread, &WorkerThread::finished, thread, &QObject::deleteLater);
thread->start();

模式 B:Worker QObject + moveToThread(推薦)

class Worker : public QObject {
    Q_OBJECT
public slots:
    void doWork() {
        // 耗時任務
        emit resultReady(data);
    }
signals:
    void resultReady(const QString &data);
};

// 使用
QThread *thread = new QThread;
Worker *worker = new Worker;
worker->moveToThread(thread);
connect(thread, &QThread::started, worker, &Worker::doWork);
connect(worker, &Worker::resultReady, this, &MainWindow::handleResult);
connect(worker, &Worker::resultReady, thread, &QThread::quit);
connect(thread, &QThread::finished, thread, &QObject::deleteLater);
connect(worker, &Worker::destroyed, thread, &QThread::quit);
thread->start();

優勢:Worker 可有槽/信號、事件循環、定時器、網絡請求,生命週期管理更清晰。

3. 同步機制代碼模板

QMutex 保護共享數據

class Counter {
    QMutex mutex;
    int value = 0;
public:
    void increment() { QMutexLocker locker(&mutex); ++value; }
    int get() { QMutexLocker locker(&mutex); return value; }
};

QReadWriteLock 多讀優化

QReadWriteLock lock;
void read() { QReadLocker locker(&lock); /* 讀取共享數據 */ }
void write() { QWriteLocker locker(&lock); /* 修改共享數據 */ }

QSemaphore 生產者-消費者

const int BufferSize = 8192;
char buffer[BufferSize];
QSemaphore freeBytes(BufferSize), usedBytes(0);

void producer() {
    for (int i=0; i

QWaitCondition 條件等待

QMutex mutex;
QWaitCondition notEmpty, notFull;
int used = 0;

void producer() {
    mutex.lock();
    while (used == BufferSize) notFull.wait(&mutex);
    buffer[used++] = data;
    notEmpty.wakeOne();
    mutex.unlock();
}
void consumer() {
    mutex.lock();
    while (used == 0) notEmpty.wait(&mutex);
    data = buffer[--used];
    notFull.wakeOne();
    mutex.unlock();
}

4. 可重入 vs 線程安全

類用途
QThread管理線程,重寫 run() 或移動 QObject 到線程
QMutex互斥鎖,配合 QMutexLocker RAII
QReadWriteLock讀寫鎖,多讀單寫,配合 QReadLocker/QWriteLocker
QSemaphore信號量,控制有限資源訪問
QWaitCondition條件變量,線程等待/喚醒
QThreadStorage線程局部存儲

規則:Qt 類默認可重入非線程安全。GUI 類(QWidget 及子類)不可重入,只能在主線程使用。

5. QObject 線程親緣性三大鐵律

  1. 子對象必須在父對象線程創建:不可將 QThread 對象作為父對象(它在另一線程創建)。
  2. 事件驅動對象綁定創建線程:定時器、網絡套接字必須在其所屬線程中啟動/連接。
  3. 刪除前清理:線程結束前刪除該線程創建的所有對象,或用 deleteLater() 安全跨線程刪除。

6. 跨線程信號槽:三種連接類型

概念定義典型類
可重入同一類的不同實例可被多線程同時調用大多數 C++ 類、Qt 非 GUI 類(QTimer, QTcpSocket...)
線程安全同一實例可被多線程同時調用QMutex, QAtomicInt, QCoreApplication::postEvent()
// 顯式指定
connect(sender, &Sender::signal, receiver, &Receiver::slot, Qt::QueuedConnection);

7. 隱式共享與線程安全

Qt 值類型(QString, QByteArray, QList, QImage...)使用原子引用計數的隱式共享(Copy-on-Write)。

  • 跨線程傳值安全:引用計數原子操作,拷貝極廉價。
  • 同一對象多線程讀寫不安全:需外部鎖保護(如 QMutex)。
  • Qt 4.0+ 保證:原子操作用汇編實現,無鎖開銷,比手工 mutex 快得多。

8. 事件循環與跨線程事件投遞

  • 主線程:QCoreApplication::exec()。
  • 子線程:QThread::exec()(在 run() 中調用)。
  • QCoreApplication::postEvent():線程安全,向任意線程對象投遞事件。
  • sendEvent():同步直接投遞,僅用於當前線程。

總結:Qt 多線程最佳實踐清單

  1. 優先用 Worker + moveToThread,避免繼承 QThread。
  2. 共享數據用 QMutex/QReadWriteLock,RAII 用 QMutexLocker。
  3. 生產消費用 QSemaphore 或 QWaitCondition。
  4. 跨線程通信用 QueuedConnection 信號槽,傳值類型利用隱式共享。
  5. GUI 操作只在主線程,耗時任務拋給工作線程。
  6. 線程對象用 deleteLater(),確保事件處理完再銷毀。
  7. 用 QThreadStorage 管理線程局部數據。

掌握這套體系,即可編寫高併發、響應迅速、線程安全的 Qt 應用。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
類型行為執行線程適用場景
Direct立即調用槽發射者線程同線程、或確保線程安全
Queued事件隊列投遞,事件循環處理接收者線程跨線程、默認安全
Auto (默認)同線程=Direct,異線程=Queued自動大多數情況