上一篇说了那么多就是想表达QMutex是怎么运行的。不过QMutex的目的是保护数据,接下来就看看QMutex保护数据的例子吧。

    例:

    从QThread派生两个类Thread和Thread2,两个类的run函数分别如下:

int number = 0; //全局变量

void Thread::run()
{
    number += 5;
    qDebug()<<"---------------";
    int val = number*3;
    qDebug()<<"thread1"<<val;
}

void Thread2::run()
{
    number += 3;
    qDebug()<<"---------------";
    int val = number*2;
    qDebug()<<"therad2"<<val;
}

两个线程的工作就是使用全局变量number来计算获得最终结果。若Thread线程先执行那么预期的结果将是Thread输出15。但是运行结果却是:

blob.png

24是怎么来的呢?number在Thread线程中+=5变为了5,然后在Thread2线程中+=3变为了8,所以在Thread线程中再计算val的值时number已经变为了8,结果就是24了。

(说明:两个run函数中都有加qDebug()<<"---------------",目的是让两个线程交替执行,不然有可能线程在一个时间片内就完成了计算,结果就是预期的了。所以此处这个qDebug纯粹是为了写这个反例,没有实际意义。)


这时候就需要QMutex上场了,根据上一篇所说的,我们需要在两个线程中都加上QMutex。

void Thread::run()
{
    mutex.lock();
    number += 5;
    qDebug()<<"---------------";
    int val = number*3;
    qDebug()<<"thread1"<<val;
    mutex.unlock();
}

void Thread2::run()
{
    mutex.lock();
    number += 3;
    qDebug()<<"---------------";
    int val = number*2;
    qDebug()<<"therad2"<<val;
    mutex.unlock();
}

运行结果:

blob.png

QMutex虽好,但使用时也要小心一点,有lock就要unlock。不然的话别的线程就惨了。比如说把Thread::run中的mutex.unlock注释掉。那么运行结果就是:

blob.png

只有Thread的结果打印出来了,那是因为Thread2还卡在mutex.lock这里,它还在问mutex你解锁了没.....