基于环形队列的生产者消费者模型

之前的Blog基于Queue的生产者消费者模型,已经谈过了基于queue的生产消费模型,其空间是可以动态分配的。而现在是基于固定大小的环形队列重写这个程序。

基于环形队列的生产消费模型

  • 环形队列采用数组模拟,用模运算来模拟环状特性

  • 环形结构起始状态和结束状态都是一样的,不好判断为空或者为满,所以就需要通过计数器或者标记位来判断满或空。另外也可以预留一个空的位置,作为满的状态。
  • 消费者总是跟在生产者的后边,且不会超过生产者
  • 生产者一直在消费者的前边,且不会超过消费者一圈。
  • head和tail指向同一个位置的时候,队列为空。
  • 当head在tail的下一个位置时,环形队列为满。

/*#####  ringqueue.cc   ####*/
#include"test.hpp"

const int num=16;

using namespace std;

void *consume_routine(void *arg)
{	
	int d;
	RingQueue *q=(RingQueue*)arg;
	for(;;)
	{
		q->PopData(d);
		cout<<"consume done,data is..."<<d<<endl;
	}
}
void *product_routine(void *arg)
{
	RingQueue *q=(RingQueue*)arg;
	srand((unsigned long)time(NULL));
	for(;;)
	{
		int d=rand()%100+1;
		q->PushData(d);
		cout<<"Product done,data is..."<<d<<endl;
		sleep(1);
	} 
}
int main()
{
	RingQueue *q=new RingQueue(num);
	pthread_t c,p;
	pthread_create(&c,NULL,consume_routine,(void*)q);
	pthread_create(&p,NULL,product_routine,(void*)q);


	pthread_join(&c,NULL);
	pthread_join(&p,NULL);


	delete(q);



	return 0;
}
/*******   test.hpp   *******/
#ifndef __TEST_HPP__
#define __TEST_HPP__

#include<vector>
#include<iostream>
#include<pthread.h>
#include<unistd.h>
#include<time.h>
#include<semaphore.h>
#include<stdlib.h>



class RingQueue
{
private:
	std::vector<int> ring;
	int cap;
	sem_t blank_sem;
	sem_t data_sem;

	int c_step;										//consume在圈中的位置
	int p_step;		  								//product在圈中的位置
private:
	void P(sem_t &sem)
	{
		sem_wait(&sem);
	}
	void V(sem_t &sem)
	{
		sem_post(&sem);
	}
public:
	RingQueue(int cap_):cap(cap_),ring(cap_)
	{
		c_step=p_step=0;							//初始时c_step和p_step在同一格
		sem_init(&blank_sem,0,cap);				//初始时需要写入的输入是整个圈的容量
		sem_init(&data_sem,0,0);					//初始时需要consume的值为0
	}
	void PushData(const int& data)					//进行数据生产
	{
		P(blank_sem);
		ring[p_step]=data;							//把数据放进去
		V(data_sem);
		p_step++;
		p_step%=cap;								//进行模运算来模拟环形特性
	}
	void PopData(int &data  )
	{
		P(data_sem);								//申请数据资源
		data=ring[c_step];							//拿到数据
		V(blank_sem);								//空出格子
		c_step++;
		c_step%=cap;
	}
	~RingQueue()
	{
		sem_destroy(&blank_sem);
		sem_destroy(&data_sem);
	}

};

#endif
******   makefile   ******

ringqueue:ringqueue
	.cc
	g++ -o  $@ $^ -lpthread -fpermissive
.PHONY:clean
clean:
	rm -f ringqueue
	

猜你喜欢

转载自blog.csdn.net/CrankyPants/article/details/85049858
今日推荐