多线程--信号量

时间:2021-01-09 20:40:34

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

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

 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,"\n");               //每16个数据进行一次换行打印

        }
        freeBytes.release();                    //单元变成空闲,生产者可用
    }
    fprintf(stderr,"\n");
}
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个数据;