zoukankan      html  css  js  c++  java
  • 多线程--信号量

    信号量可以获取多次,可以用来保护一定数量的同种资源,信号量的典型用例是控制生产者和消费者之间共享的环形缓冲区

    生产者,消费者实例中对同步的需求有两处:

     1.生产者快于消费者,将会覆盖消费者还没有读取的数据;

    2.生产者慢于消费者,将会读取到一些过期的数据;

    两种解决方案:

    1.首先使生产者填满缓冲区,然后等待消费者读取整个缓冲区;

    2.使生产者和消费者线程同时分别操作缓冲区的不同部分;

    #include <QCoreApplication>
    
    #include<QSemaphore>
    #include<QThread>
    #include<stdio.h>
    
    const int DataSize=1000;
    const int BufferSize=80;
    int buffer[BufferSize];
    
    QSemaphore freeBytes(BufferSize); //生产者信号量,目前空闲的单元数为80
    QSemaphore usedBytes(0);         //消费者信号量,目前可用的单元数为0
    
    class Producer:public QThread
    {
    public:
        Producer();
        void run();
    };
    
    Producer::Producer()
    {
    
    }
    void Producer::run()
    {
        for(int i=0;i<DataSize;i++)
        {
            freeBytes.acquire();//生产者首先获得一个空闲单元,若此时缓冲区被消费者尚未读取的数据填满,对此函数的调用就会阻塞
            buffer[i%BufferSize]=(i%BufferSize); //buffer的最大量80
            usedBytes.release();//表示这个单元被填写,消费者可以使用
        }
    
    }
    
    
    class Consumer:public QThread
    {
       public:
        Consumer();
        void run();
    
    };
    
    Consumer::Consumer()
    {
    
    }
    void Consumer::run()
    {
        for(int i=0;i<DataSize;i++)
         {
            usedBytes.acquire();   //消费和线程首先获取一个可被读取的单元,若缓冲区没有包含任何可以读取的数据,对此函数的调用阻塞
            fprintf(stderr,"%d",buffer[i%BufferSize]);//stderr标准错误流
            if(i%16==0&&i!=0)
            {
                fprintf(stderr,"
    ");               //每16个数据进行一次换行打印
    
            }
            freeBytes.release();                    //单元变成空闲,生产者可用
        }
        fprintf(stderr,"
    ");
    }
    int main(int argc, char *argv[])
    {
        QCoreApplication a(argc, argv);
        Producer producer;  //生产者线程
        Consumer consumer;  //消费者线程
        producer.start();
        consumer.start();
    
        producer.wait();
        producer.wait();
    
        return a.exec();
    }

    buffer作为缓冲区;

    生产者和消费者线程同时工作,依次输出1000个数据;

  • 相关阅读:
    1.17 Python基础知识
    反射
    面向对象——类
    异常处理
    面向对象——静态方法、类方法、属性法法,其他特殊方法
    面向对象——继承
    question
    configparser模块
    hashlib模块
    shelve模块
  • 原文地址:https://www.cnblogs.com/whitewn/p/6949641.html
Copyright © 2011-2022 走看看