生产者――消费者问题算法的实现 实验报告
一、实验内容
1.问题描述:一组生产者向一组消费者提供消息,它们共享一个有界缓冲池,生产者向其中投放消息,消费者从中取得消息。假定这些生产者和消费者互相等效,只要缓冲池未满,生产者可将消息送入缓冲池,只要缓冲池未空,消费者可从缓冲池取走一个消息。
2.功能要求:根据进程同步机制,编写一个解决上述问题的程序,可显示缓冲池状态、放数据、取数据等过程。
 
二、背景知识
1.进程管理。
2.信号量的有关知识。
三、思路
生产者的主要作用是生成一定量的数据放到缓冲区中,然后重复此过程。与此同时,消费者也在缓冲区消耗这些数据。该问题的关键就是要保证生产者不会在缓冲区满时加入数据,消费者也不会在缓冲区中空时消耗数据。为使生产者进程与消费者进程能并发执行,在两者之间设置了一个具有 n 个缓冲区的缓冲池:生产者进程从文件中读取一个数据,并将它存放到一个缓冲区中;消费者进程从一个缓冲区中取走数据,并输出此数据。生产者和消费者之间必须保持同步原则:不允许消费者进程到一个空缓冲区去取产品;也不允许生产者进程向一个已装满产品且尚未被取走的缓冲区中投放产品。实现一个生产者对多个消费者,每一次生成数随机,若为奇数为生产者生产,反之为消费者消费,因此该过程是1对N的生产者消费者问题。
四、核心代码
#include <iostream>//一个生产者,多个消费者,会在每次消费之前判断当前缓冲池有无商品
#include <time.h>//生成数随机,消费者、生产者生产和消费随机
#include <stdlib.h>
#define N 10	//产品参数
using namespace std;
/*定义生产者消费者类*/
class PPCC {
private:
	int in, out;//指向有产品的下标的指针
	int count;//缓冲区的产品数
	int buffer[N];//缓冲区,其中N为缓冲区的大小
	int mutex;//互斥信号量
	int  empty, full;//判断缓冲区是否为空或者满,信号量
public:
	/*初始化,构造生产者消费者*/
	PPCC() {
		in = 0; out = 0; count = 0;
		empty = N; full = 0; mutex = 1;
		for (int i = 0; i < N; i++)
			buffer[i] = 0;
	}
	/*生产者生产*/
	void Producer() 
	{
		if (empty == 0) {
			full = 1;
			cout << "产品已满,不能再生产" << endl;
			return;
		}
		Wait(empty);//empty--;
		buffer[out] = 1;	//生产一个产品
		out = (out + 1) % N;	//尾指针后移一位,构成循环队列
cout << "生产者生产了一个产品" << endl;
		/*对count互斥访问*/
		Wait(mutex);
		count++;
		Signal(mutex);
	}
	/*消费者消费*/
	void Consumer() 
	{
		if (empty == N) {
			cout << "没有产品,不能消费" << endl;//每次消费之前判断当前缓冲池有无商品
			return;
		}
		buffer[in] = 0;//消费一个产品
		in = (in + 1) % N;//头指针后移一位,构成循环队列
cout << "消费者消费了一个产品" << endl;
		/*对count互斥访问*/
		Wait(mutex);
		count--;
		Signal(mutex);
		if (empty <= N) 
		{
			full = 0;
			Signal(empty);//empty++;
		}
	}
	/*显示现在缓冲区的情况*/
	void Display() 
	{
		for (int i = 0; i < N; i++)
			cout << buffer[i];
		cout << endl << "一共有" << count << "个产品" << endl << endl;
	}
	void Wait(int &s) 
	{
		if (s <= 0) return;
		s--;
	}
	void Signal(int &s) 
	{
		s++;
	}
};
/*函数主体*/
int main() {
	int i = 0;
	srand(time(NULL));
	PPCC x;
	//随机执行生产者生产还是消费者消费
	cout << "初始状态" << endl; x.Display();
	do {
		if (rand() & 1)//利用比例控制生产速度,如果为奇数,为生产者生产
			x.Producer();
		else//否则为消费者消费
			x.Consumer();
		    x.Display();
		    i++;
	} while (i != 30);//(可修改次数)
	return 0;
}
五、运行结果
 
六、结论
缓冲区是临界资源,各进程必须互斥地访问,为了避免两个进程之间相互干扰,我们利用信号量机制来实现进程间互斥和同步 ,使用数组模拟的循环队列来完成缓冲区。生产者进程向缓冲区投入产品,则count加1;消费者进程向缓冲区取出产品,则count减1。
 
                    
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号