Qt中的線程是與平台無關的
QThread 提供了創建一個新線程的方法
新建一個線程,繼承QThread並重寫它的run()當調用 start()函數時會調用重載的run()函數
例:
#ifndef MYTHREAD_H #define MYTHREAD_H #include <QThread> class MyThread : public QThread { Q_OBJECT public: bool stop ; explicit MyThread(QObject *parent = 0); void run(); signals: public slots: }; #endif // MYTHREAD_H
#include "mythread.h" #include<QDebug> MyThread::MyThread(QObject *parent) : QThread(parent) { stop = false; } void MyThread::run() { for(int i=0;i<1000;i++) { if(stop)break; qDebug()<<i; QThread::sleep(1); } }
#include <QCoreApplication> #include "myobject.h" #include <QThread> #include<QDebug> #include "mythread.h" int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); MyThread myThread; myThread.start(); QThread::sleep(10); myThread.stop=true; return a.exec(); }
看一下Qt中包含的線程類:
QThread 所有線程的基類,提供了創建一個線程的方法
QThreadStorge 提供一逐線程數據存儲
QMutex 提供相互排斥的鎖,或互斥量
QMutexLocker 可以自動對QMutex加鎖與解鎖
QReadWirterLock 提供了一個可以同時讀操作的鎖
QreadLocker與QwriteLocker可以自動對QReadWriteLock加鎖與解鎖
QSempHore提供了一個整形信號量,是互斥的泛化
QWaitCondition提供了一種方法,使線程可以在被另外線程喚醒之前一直休眠
線程的同步
QMutex 提供相互排斥的鎖,或互斥量
QMetex提供了lock和Unlock函數,如果 一個已經鎖定 這個互斥量,只有這個線程unlock后其它線程才可以
訪問
把上邊的例子做一下修改,只是為了方便大家理解,這個例子沒什么作用
#ifndef MYTHREAD_H #define MYTHREAD_H #include <QThread> class QMutex; class MyThread : public QThread { Q_OBJECT private: QMutex qm; bool stop; public: explicit MyThread(QObject *parent = 0); void run(); void SetFlg(bool flg); signals: public slots: }; #endif // MYTHREAD_H
#include "mythread.h" #include<QDebug> #include<QMutex> MyThread::MyThread(QObject *parent) : QThread(parent) { stop = false; } void MyThread::SetFlg(bool flg) { qm.lock(); stop=flg; qm.unlock(); } void MyThread::run() { for(int i=0;i<1000;i++) { qm.lock(); if(stop) { qm.unlock(); break; } qDebug()<<i; QThread::sleep(1); qm.unlock(); } }
#include <QCoreApplication> #include "myobject.h" #include <QThread> #include<QDebug> #include "mythread.h" int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); MyThread myThread; myThread.start(); QThread::sleep(10); myThread.SetFlg(true); return a.exec(); }
使用QMutex時要小心因為如果 lock()后沒有unlock()會導致死鎖別的線程就
永遠也不能訪問資源了
Qt提供了QMutexLocker來解決這個問題
修改我們的app文件
#include "mythread.h" #include<QDebug> #include<QMutex> #include<QMutexLocker> MyThread::MyThread(QObject *parent) : QThread(parent) { stop = false; } void MyThread::SetFlg(bool flg) { QMutexLocker locker(&qm); stop=flg; } void MyThread::run() { QMutexLocker locker(&qm); for(int i=0;i<1000;i++) { if(stop) { break; } qDebug()<<i; QThread::sleep(1); } }
QMutexLocker會自己unluck
QMutexLocker也提供了一個mutex()成員函數返回QMutexLocker操作的互斥量。對於需要訪問互斥量是十分有用的,比如QWaitCondition::wait()。
QReadWirterLock
用mutext進行線程同步有一個問題某個時刻只許一個線程訪問資源如果同時有多個線程對共享資源進行訪問,
同時有寫操作線程那么這種情況下采用mutex就會成為程序的瓶頸。使用QReadWriteLock來實現多線程
讀操作,一個線程寫操作,寫線程執行時會阻塞所有的讀線程,而讀線程運行不需要進行同步
QReadWriteLock lock; void ReaderThread::run() { ... lock.lockForRead(); read_file(); lock.unlock(); ... } void WriterThread::run() { ... lock.lockForWrite(); write_file(); lock.unlock(); ... }
QreadLocker和QWriteLocker類是對QReadWirterLock 的簡化
它們會自動unluck();
QReadWriteLock lock; QByteArray readData() { QReadLocker locker(&lock); ... return data; }
相當於QReadWirterLock 的寫法如下
QReadWriteLock lock; QByteArray readData() { lock.lockForRead(); ... lock.unlock(); return data; }