博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
网上Qt多线程同步的一种普遍误识
阅读量:2193 次
发布时间:2019-05-02

本文共 2363 字,大约阅读时间需要 7 分钟。

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对象在所有的此类线程中是共享的,通过这样去修改,才真正地多个线程同步。为了避免大家被网上错误的讲解所误解,免得把多线程同步按照他们的方式去写,特发此文。 

如果哪里有不对,请大家给我指出,我将不胜感激!! 
我把随便参考的一个错误链接贴出来: 
Youtube视频链接:

你可能感兴趣的文章
Java并发指南2:深入理解Java内存模型JMM
查看>>
Java并发指南3:并发三大问题与volatile关键字,CAS操作
查看>>
Java并发指南4:Java中的锁 Lock和synchronized
查看>>
Java并发指南5:JMM中的final关键字解析
查看>>
Java并发指南6:Java内存模型JMM总结
查看>>
Java并发指南7:JUC的核心类AQS详解
查看>>
Java并发指南8:AQS中的公平锁与非公平锁,Condtion
查看>>
Java网络编程和NIO详解6:Linux epoll实现原理详解
查看>>
Java网络编程和NIO详解7:浅谈 Linux 中NIO Selector 的实现原理
查看>>
Java网络编程与NIO详解8:浅析mmap和Direct Buffer
查看>>
Java网络编程与NIO详解10:深度解读Tomcat中的NIO模型
查看>>
Java网络编程与NIO详解11:Tomcat中的Connector源码分析(NIO)
查看>>
深入理解JVM虚拟机1:JVM内存的结构与消失的永久代
查看>>
深入理解JVM虚拟机3:垃圾回收器详解
查看>>
深入理解JVM虚拟机4:Java class介绍与解析实践
查看>>
深入理解JVM虚拟机5:虚拟机字节码执行引擎
查看>>
深入理解JVM虚拟机6:深入理解JVM类加载机制
查看>>
深入了解JVM虚拟机8:Java的编译期优化与运行期优化
查看>>
深入理解JVM虚拟机9:JVM监控工具与诊断实践
查看>>
深入理解JVM虚拟机10:JVM常用参数以及调优实践
查看>>