Qt中线程安全的类有QMutex,QMutexLocker,QReadWriteLock,QReadLocker,QWriteLocker,QSemaphore(信号量),QThreadStorage<T>,QWaitCondition

#include<iostream>
#include<QThread>
#include<QMutex>
#include<QWaitCondition>
using namespace std;

QMutex mutex;
QWaitCondition wait1;

class Thread1:public QThread{
public:
    void run(){
        mutex.lock();
        for(int i=0;i<5;i++){
            msleep(500);
            cout << "t1" << endl;
        }
        mutex.unlock();
        wait1.wakeOne();
    }
};

class Thread2:public QThread{
public:
    void run(){
        wait1.wait(&mutex);
        for(int i=0;i<5;i++){
            cout << "t2" << endl;
        }
    }
};

int main(){
    Thread1 t1;
    Thread2 t2;
    t1.start();
    t2.start();
    t1.wait();
    t2.wait();
}



结果是t1完全跑完后再跑t2:


t1


t1


t1


t1


t1


t2


t2


t2


t2


t2



也可以用QMutexLocker,这样是不是看起来更简单一点呢?


#include<iostream>
#include<QThread>
#include<QMutex>
#include<QMutexLocker>
using namespace std;

QMutex mutex;

class Thread1:public QThread{
public:
    void run(){
        QMutexLocker locker(&mutex);
        for(int i=0;i<5;i++){
            msleep(500);
            cout << "t1" << endl;
        }
    }
};

class Thread2:public QThread{
public:
    void run(){
        QMutexLocker locker(&mutex);
        for(int i=0;i<5;i++){
            cout << "t2" << endl;
        }
    }
};

int main(){
    Thread1 t1;
    Thread2 t2;
    t1.start();
    t2.start();
    t1.wait();
    t2.wait();
}

结果同上



read与write的略有不同,读锁大家都可以读,写锁则只能一个一个写


#include<QReadWriteLock>
#include<QFile>
#include<QThread>
#include<QTextStream>
#include<iostream>
#include<QTemporaryFile>
#include<QReadLocker>
using namespace std;

QReadWriteLock readWriteLocker;
const QString fileName = "test.txt";

void readFile(QFile& file){
    QTextStream ts(&file);
    QString str = ts.readAll();
    cout << str.toStdString() << endl;
}

class Read1:public QThread{
public:
    void run(){
        //加了读锁后,如果sleep,后面的可以不用等,直接读
        //但是如果这里是lockForWrite()的话,无论这里sleep多久,后面的线程都得等
        readWriteLocker.lockForRead();
        msleep(1000);
        QFile file(fileName);
        if(file.open(QIODevice::ReadWrite)){
            cout << "read1 start reading..." << endl;
            readFile(file);
        }
        readWriteLocker.unlock();
        file.close();//解锁后再关
    }
};

class Read2:public QThread{
public:
    void run(){
        readWriteLocker.lockForRead();
        QFile file(fileName);
        if(file.open(QIODevice::ReadWrite)){
            cout << "read2 start reading..." << endl;
            readFile(file);
        }else{
            cout << "can not open!" << endl;
        }
        readWriteLocker.unlock();
        file.close();
    }
};

int main(){
    Read1 r1;
    Read2 r2;
    r1.start();
    r2.start();
    r1.wait();
    r2.wait();
}

read2 start reading...
This is a test file!

read1 start reading...
This is a test file!



生产者与消费者


#include<iostream>  
#include<QThread>  
#include<stack>  
#include<QMutex>  
#include<QWaitCondition>  
using namespace std;  

stack<int> sk;  
const int sum = 10;  
const int maxSize = 3;  
QMutex mutex;  
QWaitCondition producerWait;  
QWaitCondition consumerWait;  

class Producer:public QThread{  
public:  
    void run(){  
        for(int i=1;i<=sum;i++){  
            if(sk.size()==maxSize){  
                cout << "stack is full,wait consumer!" << endl;  
                producerWait.wait(&mutex);  
            }  
            sk.push(i);  
            //mutex.lock();  
            msleep(180);  
            //mutex.unlock();  
            cout << "produce:" << i << endl;  
            consumerWait.wakeAll();  
        }  
    }  
};  

class Consumer:public QThread{  
public:  
    void run(){  
        int i = 0;  
        for(int j=1;j<=sum;j++){  
            if(sk.empty()){  
                cout << "stack is empty,wait producer!" << endl;  
                consumerWait.wait(&mutex);  
            }  
            i = sk.top();  
            sk.pop();  
            //mutex.lock();  
            msleep(300);  
            //mutex.unlock();  
            cout << "consume:" << i << endl;  
            producerWait.wakeAll();  
        }  
    }  
};  

int main(){  
    Consumer con;  
    Producer pro;  
    pro.start();  
    con.start();  
    con.wait();  
    pro.wait();  
}


stack is empty,wait producer!


produce:1


produce:2


consume:2


produce:3


produce:4


consume:3


produce:5


consume:5


produce:6


produce:7


stack is full,wait consumer!


consume:6


produce:8


stack is full,wait consumer!


consume:7


produce:9


stack is full,wait consumer!


consume:8


produce:10


consume:9


consume:10


consume:4


consume:1