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 對象。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 實現「緩衝區滿/空」的精確等待與通知,避免忙等待,見文中完整生產者/消費者代碼示例。
// 非線程安全的計數器
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 可重入,非 GUI 子類(QTimer、QTcpSocket 等)也可重入,但建議在創建線程中使用。QThread 作為 parent)。QThread 前確保其創建的所有對象已銷毀(可在 run() 棧上創建)。每個線程可擁有事件循環(主線程 QCoreApplication::exec(),子線程 QThread::exec()),使得非 GUI 類(定時器、Socket、進程)可在子線程工作。moveToThread() 可改變對象線程親緣,deleteLater() 安全跨線程刪除對象。
三種連接類型:
跨線程直接連接不安全;QObject::connect() 本身線程安全。
Qt 值類型(QString、QVector 等)採用隱含共享(COW),引用計數採用原子操作(匯編實現),無鎖、高效。Qt 4.0+ 保證隱含共享類跨線程拷貝安全,可視為普通可重入類型使用。但多線程同時讀寫同一實例仍需加鎖。
掌握上述核心概念與模式,即可構建健壯、高效的 Qt 多線程應用。建議結合官方文檔與實踐項目深入理解。