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

Qt 多線程程序設計完整指南

     編輯:關於C語言

Qt 多線程程序設計完整指南

Qt 通過三大核心機制提供強大的跨平台多線程支持:平台無關的線程類、線程安全的事件投遞、跨線程的信號-槽連接。這使得開發高效、響應式的多線程應用變得簡單,並能充分發揮多核處理器優勢。自 Qt 4.0 起,線程支持始終內置啟用。

核心線程相關類

類名功能描述
QThread管理線程生命周期,提供 start()、run()、exec() 等核心方法
QThreadStorage提供線程局部存儲(TLS)機制
QMutex / QMutexLocker互斥鎖與自動加解鎖輔助類,保護共享數據
QReadWriteLock / QReadLocker / QWriteLocker讀寫鎖,允許多線程並發讀、獨佔寫,提高並發性能
QSemaphore信號量,互斥鎖的泛化,可保護固定數量的同類資源
QWaitCondition條件變量,線程等待/喚醒機制,配合互斥鎖使用

創建線程的標準模式

class MyThread : public QThread {
    Q_OBJECT
protected:
    void run() override {
        // 線程執行邏輯
    }
};

// 使用方式
MyThread *thread = new MyThread();
thread->start();  // 啟動線程,自動調用 run()

關鍵規則:

  • QCoreApplication::exec() 必須在主線程(GUI 線程)調用。
  • 創建 QThread 前必須先構造 QApplication/QCoreApplication 對象。
  • GUI 類(QWidget 及子類)不可重入,僅能在主線程使用。

線程同步機制深度解析

互斥鎖

QMutex mutex;
mutex.lock();
// 訪問共享資源
mutex.unlock();

// 推薦使用 RAII 風格
QMutexLocker locker(&mutex);
// 自動加鎖/解鎖

讀寫鎖——提升並發度

QReadWriteLock lock;

void ReaderThread::run() {
    lock.lockForRead();
    read_file();
    lock.unlock();
}

void WriterThread::run() {
    lock.lockForWrite();
    write_file();
    lock.unlock();
}

多讀者可並發,寫者獨佔,比互斥鎖並發性更強。

信號量——生產者/消費者模型經典實現

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

class Producer : public QThread {
    void run() override {
        for (int i = 0; i < DataSize; ++i) {
            freeBytes.acquire();           // 等待空槽
            buffer[i % BufferSize] = "ACGT"[qrand() % 4];
            usedBytes.release();           // 通知有數據
        }
    }
};

class Consumer : public QThread {
    void run() override {
        for (int i = 0; i < DataSize; ++i) {
            usedBytes.acquire();           // 等待數據
            putchar(buffer[i % BufferSize]);
            freeBytes.release();           // 釋放槽位
        }
    }
};

等待條件——精確控制線程喚醒

QWaitCondition 配合 QMutex 實現「緩衝區滿/空」的精確等待與通知,避免忙等待,見文中完整生產者/消費者代碼示例。

可重入與線程安全

  • 可重入:多線程同時調用同一類的不同實例的成員函數安全。大多數 C++ 類天然可重入。
  • 線程安全:多線程同時調用同一實例的成員函數安全。需用鎖保護共享數據。
// 非線程安全的計數器
class Counter { int n; public: void increment() { ++n; } };

// 線程安全版本
class Counter {
    mutable QMutex mutex;
    int n = 0;
public:
    void increment() { QMutexLocker locker(&mutex); ++n; }
    int value() const { QMutexLocker locker(&mutex); return n; }
};

mutable 允許在 const 成員函數中加鎖。

QObject 與線程親緣關係

  • QObject 可重入,非 GUI 子類(QTimer、QTcpSocket 等)也可重入,但建議在創建線程中使用。
  • 三大約束:
    1. 子對象必須在父對象所在線程創建(勿傳 QThread 作為 parent)。
    2. 事件驅動對象(定時器、網絡模塊)僅在所屬線程使用。
    3. 刪除 QThread 前確保其創建的所有對象已銷毀(可在 run() 棧上創建)。

逐線程事件循環與跨線程信號-槽

每個線程可擁有事件循環(主線程 QCoreApplication::exec(),子線程 QThread::exec()),使得非 GUI 類(定時器、Socket、進程)可在子線程工作。moveToThread() 可改變對象線程親緣,deleteLater() 安全跨線程刪除對象。

三種連接類型:

  1. 直接連接:發射線程立即執行槽函數。
  2. 隊列連接:槽函數投遞到接收者線程事件隊列,稍後執行。
  3. 自動連接(默認):同線程用直接,跨線程用隊列。

跨線程直接連接不安全;QObject::connect() 本身線程安全。

隱含共享與多線程

Qt 值類型(QString、QVector 等)採用隱含共享(COW),引用計數採用原子操作(匯編實現),無鎖、高效。Qt 4.0+ 保證隱含共享類跨線程拷貝安全,可視為普通可重入類型使用。但多線程同時讀寫同一實例仍需加鎖。

掌握上述核心概念與模式,即可構建健壯、高效的 Qt 多線程應用。建議結合官方文檔與實踐項目深入理解。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved