网上Qt多线程同步的一种普遍误识

http://blog.csdn.net/gulansheng/article/details/44851727

Youtube上有一个很出名的Qt视频教程,讲得简练精要。但是在他讲到的Qt线程同步一集的时候,我凭着自己的经验,感觉他讲得是错的。于是在网上大范围的搜索“qt线程同步”这个关键字,试图找到一些线索,以证明视频教程中的错误。但是看了很多个博客之后,我发现大家都是千篇一律,很是吃惊。真是误导大家。所以特意写这篇文章来证实一下。 
首先我们要知道为什么要用线程同步?那是因为在多线程编程里面,会有一些敏感数据不允许被多个线程同时访问,此时就使用同步访问技术,保证数据在任何时刻,最多有一个线程访问,以保证数据的完整性。 
在这里我们引用一个网上较为流行的一个例子。如下所示,这是一个线程的实现:

class Thread : public QThread   
{  
public:  
    Thread();  
    void stop();  
protected:  
    virtual void run();  
private:  
    bool m_stop;  
};  
Thread::Thread()  
{  
    m_stop = false;  
}  
void Thread::stop()  
{  
    m_stop = true;  
}  
void Thread::run()  
{  
    while (!m_stop)  
    {  
        sleep(1);  
        qDebug("vic.MINg!");  
    }  
    qDebug("end!");  
} 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

Qt中的线程是以对象的形式存在的。如果我们在main函数中生成几个此类的线程对象,如下:

    Thread m1;
    Thread m2;
    Thread m3;

    m1.start();
    m2.start();
    m3.start();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

那么m1,m2,m3之间会有我们自己定义的共享数据存在吗?显然,从C++对象的概念出发来理解,他们之间是不会存在这些共享数据的。因为各个对象会维护各自对象空间里的变量。按上面例子中的代码来看,m1,m2,m3分别有着一个自己的m_stop,那我们还有必要对这个m_stop来做同步操作吗?显然是没有必要的。而网上的多数例子,以及那个Youtube的视频却对m_stop做了同步操作,引用原文的代码:

//thread.h头文件,添加互斥量对象  
private:  
    ...  
    QMutex mutex;  
};  
void Thread::run()  
{  
    forever {  
        mutex.lock();  
        if (m_stop) {  
            m_stop = false;  
            mutex.unlock();  
            break;  
        }  
        mutex.unlock();  
        qDebug("vic.MINg!");  
    }  
    qDebug("end!");  
}  
void Thread::stop()  
{  
    mutex.lock();  
    m_stop = true;  
    mutex.unlock();  
} 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

文中的意思是使用QMutex保护上面的线程类的m_stop布尔变量,我们就纳闷了,一个不被多个线程共享的数据还需要被保护呢?其中一个线程对象把这个变量改变了,其他线程对象的这个变量又不会受到什么影响。这样做又有什么意义可言。 
且不争论这个,这还不算最大的问题所在。最大的问题是定义的互斥变量也是作为类的成员变量来定义的。那么由这个线程类生成m1,m2,m3对象势必是三个不相干的互斥量,你怎么可能因为把m1的互斥量上锁,而不能让m2对自己的互斥量上锁呢?也就是说,这三个线程压根不是被同一个互斥量来协调,以达到同步的。因此,网上的多数Qt多线程同步的例子可以说是错误的。 
线程同步,首先你必须保证多个线程受控于共有的一个互斥量,我们想达到共有一个互斥量需要将互斥量定义为静态变量才对。如下所示:

class Thread : public QThread
{
public:
    Thread();
    ~Thread();
private:
    void run();
public:
    QString name;
    static QMutex  m;//只有这种情况下,互斥量才是被所有此类线程所共享的
};
//这一句最好定义在对应的cpp文件中,避免重复定义
QMutex MyThread::m; //静态对象必须定义
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

由C++对象的特征我们可以知道,以上的QMutex对象在所有的此类线程中是共享的,通过这样去修改,才真正地多个线程同步。为了避免大家被网上错误的讲解所误解,免得把多线程同步按照他们的方式去写,特发此文。 
如果哪里有不对,请大家给我指出,我将不胜感激!! 
我把随便参考的一个错误链接贴出来:http://mobile.51cto.com/symbian-272643.htm 
Youtube视频链接:http://www.youtube.com/playlist?list=PL2D1942A4688E9D63






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值