您的位置:首页 > 编程语言 > Qt开发

QSemaphore----Qt信号量

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

具体先看看QSemaphore 的介绍吧~

QSemaphore 它的成员函数是

[cpp] view
plain copy

QSemaphore ( int n = 0 )//建立对象时可以给它n个资源  

~QSemaphore ()  

void acquire ( int n = 1 )// 这个操作一次减少n个资源,如果现有资源不到n个就会阻塞  

int available () const   //返回当前可用的QSemaphore资源个数  

void release ( int n = 1 )//这个操作一次增加n个资源  

bool tryAcquire ( int n = 1 )//类似于acquire,但是申请不到n个资源时不会阻塞会立即返回  

bool tryAcquire ( int n, int timeout )  

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

[cpp] view
plain copy

 const int DataSize = 100000;//要生产的数据个数  

 const int BufferSize = 8192;//用于盛数据的缓存大小  

 char buffer[BufferSize];  

  

//要定义两个信号量,一个用于表示自由空间,一个用于表示已用空间  

 QSemaphore freeBytes(BufferSize);//自由空间初始化大小当然等于缓存大小啦  

 QSemaphore usedBytes;  

  

class Producer : public QThread  

 {  

 public:  

     void run();  

 };  

  

 void Producer::run()  

 {  

     qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));  

     for (int i = 0; i < DataSize; ++i) {  

         freeBytes.acquire();//申请一个自由空间,没有就阻塞  

         buffer[i % BufferSize] = "ACGT"[(int)qrand() % 4];  

         usedBytes.release();//已用空间增加一个,有货啦!  

     }  

 }  

  

  

class Consumer : public QThread  

 {  

 public:  

     void run();  

 };  

  

 void Consumer::run()  

 {  

     for (int i = 0; i < DataSize; ++i) {  

         usedBytes.acquire();  

         fprintf(stderr, "%c", buffer[i % BufferSize]);  

         freeBytes.release();  

     }  

     fprintf(stderr, "\n");  

 }  

  

int main(int argc, char *argv[])  

 {  

     QCoreApplication app(argc, argv);  

     Producer producer;  

     Consumer consumer;  

     producer.start();  

     consumer.start();  

     producer.wait();  

     consumer.wait();  

     return 0;  

 }  

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

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

以下是SemaphoresThread 的描述

[cpp] view
plain copy

/// \author qyvlik  

/// \abstract  

/// \version 0.0.1  

/// \date 2015/03/08  

///  

  

#ifndef SEMAPHORESTHREAD_H  

#define SEMAPHORESTHREAD_H  

  

#include <QObject>  

#include <QSemaphore>  

#include <QList>  

#include <QThread>  

  

//// print data to the console ///  

#include <QDebug>  

#include <stdio.h>  

//// print data to the console ///  

  

class SemaphoresThread : public QThread  

{  

    Q_OBJECT  

  

public:  

    explicit SemaphoresThread(QObject *parent = 0);  

    ~SemaphoresThread();  

  

protected:  

    static const int BufferSize;    // 总的可被生产者使用的空间大小  

    static const int DataSize;      //  

  

    static QSemaphore freeBytes;    // 全局静态对象,在生产者中,用于累减可用来生成的资源的空间大小 ; 在消费者中,被累加.  

    static QSemaphore usedBytes;    // 全局静态对象,在生产者中,用于累加可用来生成的资源的空间大小 ; 在消费者中,被累减.  

  

    static QList<int> data;         // 全局静态数据对象  

  

    virtual void run() = 0;  

  

};  

  

#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

#ifndef PRODUCER_H  

#define PRODUCER_H  

  

#include "SemaphoresThread.h"  

#include <QMutex>  

  

class Producer : public SemaphoresThread  

{  

    Q_OBJECT  

public:  

    explicit Producer(QObject *parent = 0);  

    ~Producer();  

  

protected:  

    void run();  

////////// static function to operator ProducerCount //////////  

    static void addProducer();  

    static void removeProducer();  

    static int producerCount();  

  

private:  

    static int ProducerCount;  

    static QMutex mutex;  

};  

  

#endif // PRODUCER_H  

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

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

[cpp] view
plain copy

///////////////// 生产者 //////////////////////////////  

/// \brief Producer::run  

/// 通过 Producer::DataSize / Producer::producerCount() 得知每个生产者的工作量  

/// 如果 Producer::producerCount() % Producer::DataSize != 0 ;将会发生运行错误!  

void Producer::run()  

{  

    for (int i = 0; i < Producer::DataSize / Producer::producerCount(); ++i) {  

        Producer::freeBytes.acquire();  

        Producer::data.append(1);  

        printf("%d",Producer::data.last());  

        fflush(stdout);  

        Producer::usedBytes.release();  

    }  

}  

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

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

[cpp] view
plain copy

/////////// run ///////////////////  

/// \brief Consumer::run  

/// 用来消费 data 中的数据的  

void Consumer::run()  

{  

    for (int i = 0; i < SemaphoresThread::DataSize; ++i) {  

        SemaphoresThread::usedBytes.acquire();  // 这个操作一次减少1个资源,如果现有资源不到1个就会阻塞  

  

        printf("%d",Consumer::data.at(i)+1);  

        fflush(stdout);  

  

        SemaphoresThread::freeBytes.release(); // 这个操作一次增加1个资源  

    }  

}  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Qt 信号量 QSemaphore