现在的位置: 首页 > 综合 > 正文

QT中线程及其同步的用法

2013年11月23日 ⁄ 综合 ⁄ 共 4147字 ⁄ 字号 评论关闭

一个进程可以分成多个线程,每个线程有自己的Register Set(寄存器组)和Stack,但共享进程的Heap、Data、Code (见下图)


创建线程:

       在Qt中要创建线程,第一步是继承QThread类,第二步是实现其中的run()函数,该方法为protected型,由start()函数来调用。下面是例子:

 

        //Producer.h   
  1. #ifndef PRODUCER_H   
  2. #define PRODUCER_H   
  3. #include <QThread>   
  4. #include <QString>   
  5. class Producer public QThread  
  6.  
  7. public 
  8.     Producer(const QString &prefix);  
  9.     void stopThread(bool isStop);  
  10. protected 
  11.     void produceMessage(int x);  
  12.     void run();  
  13. private 
  14.     QString m_prefix  
  15.     bool stopThreads  
  16. };  
  17. #endif // PRODUCER_H   
  18. //Producer.cpp   
  19. #include <QDebug>   
  20. #include "Producer.h"   
  21. Producer::Producer(const QString &prefix) QThread()  
  22.  
  23.     m_prefix prefix;  
  24.     stopThreads false 
  25.  
  26. void Producer::stopThread(bool isStop)  
  27.     stopThreads isStop;  
  28.  
  29. void Producer::produceMessage(int x)  
  30.  
  31.     qDebug() << QString("Producing %1: %2").arg(m_prefix).arg(x);  
  32.  
  33. void Producer::run()  
  34.     for(int 0; !stopThreads; i++)  
  35.         produceMessage(i);  
  36.         msleep(rand()000+1);  
  37.      
  38.  
  39. //main.cpp   
  40. #include <QApplication>   
  41. #include <QMessageBox>   
  42. #include <QDebug>   
  43. #include "Producer.h"   
  44. bool stopThreads false 
  45. int main(int argc, char *argv[])  
  46.  
  47.     QApplication a(argc, argv);  
  48.     Producer pa("A"); //创建线程对   
  49.     Producer pb("B");  
  50.     pa.start();  // 启动线程  
  51.     pb.start();  
  52.     QMessageBox::information( 0, "Threading""Close me to stop!" );   
  53.     pa.stopThread(true);  
  54.     pb.stopThread(true);  
  55.     pa.wait();  //等待线程结束  
  56.     pb.wait();  
  57.     return 0;  
  58.  


线程同步:

        多个线程在运行的时候,可以看作是并行的。当线程之间有共享数据时,为了使得数据状态能够保持连贯性而不被破坏,需要使用线程同步来保护某数据或者某段代码(即把某数据的存取或者某段代码的执行由并行变成串行,从而达到保护的目的)。而线程中对数据或代码的保持一般使用“锁”(在QT中叫mutex)来把它们“锁”住,使得在每个时刻这个数据/代码只能被一个线程访问。QT中的mutex使用有下面几种:

  • QMutex
  • QMutexLocker
  • QReadWriteLock
  • QReadLocker / QWriteLocker
  • QSemaphore

 

//QMutex: 保护lock()与unlock()之间的代码   
  1. QMutex mutex;  
  2. mutex.lock();  
  3. //需要保护的代码或数据存取   
  4. mutex.unlock();  
  5. //QLocker: 保护从QLocker对象创建后的整个函数体内的代码,函数结束后该locker会自动释放“锁”
      
  6. void fun()  
  7.     QMutexLocker locker(&mutex);  
  8.     //some other code  
  9.  
  10. //QReadWriteLock与QMutex比较相似,不过它提供的函数是:lockForRead()、lockForWrite()  
  11. //同样,QReadLocker、QWriteLocker与QLocker的使用相似,能够自动释放“锁”   
  12. //QSemaphore: 上面几种“锁”只能保护一个数据,如果有多个数据要保护,则需要使用QSemaphore
      
  13. QSemaphore s( 10 );  
  14. s.acquire();      // s.available() 9  
  15. s.acquire(5);     // s.available() 4  
  16. s.release(2);     // s.available() 6  
  17. s.release();      // s.available() 7  
  18. s.release(5);     // s.available() 12  
  19. s.tryAcquire(15); // s.available() 12  

从上面可以看出:以“Locker”结尾的“锁”用起来更加方便,因为它的对象在销毁时会自动释放锁;而不带"Locker"锁在使用时要注意处理如异常、条件判断等以保证锁能够被释放,否则可能会造成线程“锁”不释放,而被“锁”住的资源/代码不能够被别的线程访问。

抱歉!评论已关闭.