QSemaphore----Qt信号量

来源:互联网 发布:破解版软件网站 编辑:程序博客网 时间:2024/04/27 16:12

QSemaphore 能够提供类似于生产者消费者的模式,既一个生产者进行生成,另一个消费者进行消费。(在多线程中保护多个数据的一个类)

具体先看看QSemaphore 的介绍吧~

QSemaphore 它的成员函数是

[cpp] view plain copy
  1. QSemaphore ( int n = 0 )//建立对象时可以给它n个资源  
  2. ~QSemaphore ()  
  3. void acquire ( int n = 1 )// 这个操作一次减少n个资源,如果现有资源不到n个就会阻塞  
  4. int available () const   //返回当前可用的QSemaphore资源个数  
  5. void release ( int n = 1 )//这个操作一次增加n个资源  
  6. bool tryAcquire ( int n = 1 )//类似于acquire,但是申请不到n个资源时不会阻塞会立即返回  
  7. bool tryAcquire ( int n, int timeout )  

下面举生产者-消费者例子说明


[cpp] view plain copy
  1.  const int DataSize = 100000;//要生产的数据个数  
  2.  const int BufferSize = 8192;//用于盛数据的缓存大小  
  3.  char buffer[BufferSize];  
  4.   
  5. //要定义两个信号量,一个用于表示自由空间,一个用于表示已用空间  
  6.  QSemaphore freeBytes(BufferSize);//自由空间初始化大小当然等于缓存大小啦  
  7.  QSemaphore usedBytes;  
  8.   
  9. class Producer : public QThread  
  10.  {  
  11.  public:  
  12.      void run();  
  13.  };  
  14.   
  15.  void Producer::run()  
  16.  {  
  17.      qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));  
  18.      for (int i = 0; i < DataSize; ++i) {  
  19.          freeBytes.acquire();//申请一个自由空间,没有就阻塞  
  20.          buffer[i % BufferSize] = "ACGT"[(int)qrand() % 4];  
  21.          usedBytes.release();//已用空间增加一个,有货啦!  
  22.      }  
  23.  }  
  24.   
  25.   
  26. class Consumer : public QThread  
  27.  {  
  28.  public:  
  29.      void run();  
  30.  };  
  31.   
  32.  void Consumer::run()  
  33.  {  
  34.      for (int i = 0; i < DataSize; ++i) {  
  35.          usedBytes.acquire();  
  36.          fprintf(stderr, "%c", buffer[i % BufferSize]);  
  37.          freeBytes.release();  
  38.      }  
  39.      fprintf(stderr, "\n");  
  40.  }  
  41.   
  42. int main(int argc, char *argv[])  
  43.  {  
  44.      QCoreApplication app(argc, argv);  
  45.      Producer producer;  
  46.      Consumer consumer;  
  47.      producer.start();  
  48.      consumer.start();  
  49.      producer.wait();  
  50.      consumer.wait();  
  51.      return 0;  
  52.  }  


以上是一对一的模式,一般来说,生产者多于消费者或者消费者多于生产者的情况很常见(消费者为复数或者生产者为复数什么的也很常见的),接下来提供一个复数生产者单数消费者的例子吧~

==============================================

以下是SemaphoresThread 的描述

[cpp] view plain copy
  1. /// \author qyvlik  
  2. /// \abstract  
  3. /// \version 0.0.1  
  4. /// \date 2015/03/08  
  5. ///  
  6.   
  7. #ifndef SEMAPHORESTHREAD_H  
  8. #define SEMAPHORESTHREAD_H  
  9.   
  10. #include <QObject>  
  11. #include <QSemaphore>  
  12. #include <QList>  
  13. #include <QThread>  
  14.   
  15. //// print data to the console ///  
  16. #include <QDebug>  
  17. #include <stdio.h>  
  18. //// print data to the console ///  
  19.   
  20. class SemaphoresThread : public QThread  
  21. {  
  22.     Q_OBJECT  
  23.   
  24. public:  
  25.     explicit SemaphoresThread(QObject *parent = 0);  
  26.     ~SemaphoresThread();  
  27.   
  28. protected:  
  29.     static const int BufferSize;    // 总的可被生产者使用的空间大小  
  30.     static const int DataSize;      //  
  31.   
  32.     static QSemaphore freeBytes;    // 全局静态对象,在生产者中,用于累减可用来生成的资源的空间大小 ; 在消费者中,被累加.  
  33.     static QSemaphore usedBytes;    // 全局静态对象,在生产者中,用于累加可用来生成的资源的空间大小 ; 在消费者中,被累减.  
  34.   
  35.     static QList<int> data;         // 全局静态数据对象  
  36.   
  37.     virtual void run() = 0;  
  38.   
  39. };  
  40.   
  41. #endif // SEMAPHORESTHREAD_H  
    static const int BufferSize;    // 总的可被生产者使用的空间大小
    static const int DataSize;      //
    static QSemaphore freeBytes;    // 全局静态对象,在生产者中,用于累减可用来生成的资源的空间大小 ; 在消费者中,被累加.
    static QSemaphore usedBytes;    // 全局静态对象,在生产者中,用于累加可用来生成的资源的空间大小 ; 在消费者中,被累减.
    static QList<int> data;         // 全局静态数据对象

====================================
我们的Producer类继承自SemaphoresThread 

[cpp] view plain copy
  1. #ifndef PRODUCER_H  
  2. #define PRODUCER_H  
  3.   
  4. #include "SemaphoresThread.h"  
  5. #include <QMutex>  
  6.   
  7. class Producer : public SemaphoresThread  
  8. {  
  9.     Q_OBJECT  
  10. public:  
  11.     explicit Producer(QObject *parent = 0);  
  12.     ~Producer();  
  13.   
  14. protected:  
  15.     void run();  
  16. ////////// static function to operator ProducerCount //////////  
  17.     static void addProducer();  
  18.     static void removeProducer();  
  19.     static int producerCount();  
  20.   
  21. private:  
  22.     static int ProducerCount;  
  23.     static QMutex mutex;  
  24. };  
  25.   
  26. #endif // PRODUCER_H  

增加了两个静态对象,用于记录Producer构造的次数与构造的个数

通过构造的个数来计算每个Producer 对象的工作量

[cpp] view plain copy
  1. ///////////////// 生产者 //////////////////////////////  
  2. /// \brief Producer::run  
  3. /// 通过 Producer::DataSize / Producer::producerCount() 得知每个生产者的工作量  
  4. /// 如果 Producer::producerCount() % Producer::DataSize != 0 ;将会发生运行错误!  
  5. void Producer::run()  
  6. {  
  7.     for (int i = 0; i < Producer::DataSize / Producer::producerCount(); ++i) {  
  8.         Producer::freeBytes.acquire();  
  9.         Producer::data.append(1);  
  10.         printf("%d",Producer::data.last());  
  11.         fflush(stdout);  
  12.         Producer::usedBytes.release();  
  13.     }  
  14. }  

===============================================

消费者,就仅仅打印数据了

[cpp] view plain copy
  1. /////////// run ///////////////////  
  2. /// \brief Consumer::run  
  3. /// 用来消费 data 中的数据的  
  4. void Consumer::run()  
  5. {  
  6.     for (int i = 0; i < SemaphoresThread::DataSize; ++i) {  
  7.         SemaphoresThread::usedBytes.acquire();  // 这个操作一次减少1个资源,如果现有资源不到1个就会阻塞  
  8.   
  9.         printf("%d",Consumer::data.at(i)+1);  
  10.         fflush(stdout);  
  11.   
  12.         SemaphoresThread::freeBytes.release(); // 这个操作一次增加1个资源  
  13.     }  
  14. }  
0 0