生产者和消费者模型(可以多对多,一对多、多对一、一对一)c++实现,没有使用pthread,时间片模拟并发

生产者和消费者

nepu的恶臭作业

参考: link.
link.

#include <iostream>
#include <time.h>
#include <stdlib.h>
#include <vector>
#include <string>
#include <windows.h>
#include <sstream>
#include <random>
#include <Queue>
#define N 3	//产品数量,缓冲池最大数量,想改可以改,随意,数量少点能快速体现堵塞的时候,该程序可以避免死锁。
#define processNum 50		  //进程最多个数,也可以改,随意。

		using namespace std;
class PCB;
PCB* wakeup(queue<PCB*>*& list);
PCB* block(queue<PCB*>*& list, PCB* pcb);
int food = 0;//纪录缓冲池食物数量
//int morefood = 0;//在生产者手中的食物
//int lessfood = 0;//消费者想要食物但是食物不够,不够的数量

//记录型信号量
typedef struct semaphore      //信号量 
{
	int value; 				  //信号量的值(资源信号量)
	queue<PCB*>* list; //信号量队列指针(阻塞队列)
}semaphore;

queue<PCB*> producerCongestionQueue;//等待信号量empty的阻塞队列
queue<PCB*> consumerCongestionQueue;//等待信号量full的阻塞队列
queue<PCB*> shareCongestionQueue;//等待信号量mutex的阻塞队列
int mutex_c = 1;
int full_c = 0;
int empty_c = N;
semaphore Empty = { N, &producerCongestionQueue };
semaphore Full = { 0, &consumerCongestionQueue };
semaphore Mutex = { 1, &shareCongestionQueue };

class PCB {
public:
	string name;//进程名称
	int code;   //进程编号
	int pc;//0-6,指令指针、断点
	int time;//时间片
	int state;//状态(执行1、堵塞0)
	char reason;//阻塞原因(mutex、empty、full)
	int roleFlag;//生产者1或消费者0
	PCB() = default;
	static PCB* CreatePcb(char* name) {
		PCB* p = (PCB*)malloc(sizeof(PCB));
		if (name != NULL) {
			p->name = name;
		}
		else {
			p->name = "default";
		}
		return p;
	}
	void wait(semaphore* S) {
		S->value--;
		if (S->value >= 0)                           //资源条件满足 
		{

			if (this->roleFlag == 1) {					//生产者
				if (this->pc == 2)
				{
					cout << this->name << "   成功,生产者申请获取缓冲池,Empty值满足条件" << "  Empty值" << Empty.value << endl;

				}
				else if (this->pc == 3)
				{
					cout << this->name << "   成功,生产者申请获取缓冲池,Mutex值满足条件" << "  Mutex值" << Mutex.value << endl;
				}
			}
			else if (this->roleFlag == 0)             //消费者
			{
				if (this->pc == 1)
				{
					cout << this->name << "   成功,消费者申请获取缓冲池,Full值满足条件" << "  Full值" << Full.value << endl;
				}
				else if (this->pc == 2)
				{
					cout << this->name << "   成功,消费者申请获取缓冲池,Mutex值满足条件" << "  Mutex值" << Mutex.value << endl;
					mutex_c = 0;//占有
				}
			}
			this->pc++;
		}
		else if (S->value < 0)						//资源条件不满足满足
		{
			this->state = 0; //状态设置为堵塞
			if (this->roleFlag == 1) {					//生产者不能放,即生产者进程被阻塞 
				if (this->pc == 2) {
					cout << this->name << "   失败,生产者申请获取缓冲池,Empty值不满足条件" << "  Empty值" << Empty.value << endl;
				}
				else if (this->pc == 3) {
					cout << this->name << "   失败,生产者申请获取缓冲池,Mutex值不满足条件" << "  Mutex值" << Mutex.value << endl;

				}
			}
			else if (this->roleFlag == 0) {			//消费者进程被阻塞 
				if (this->pc == 1) {
					cout << this->name << "   失败,消费者申请获取缓冲池,Full值不满足条件" << "  Full值" << Full.value << endl;

				}
				else if (this->pc == 2) {
					cout << this->name << "   失败,消费者申请获取缓冲池,Mutex值不满足条件" << "  Mutex值" << Mutex.value << endl;

				}
			}
			block(S->list, this);		          //阻塞进程		
		}
	}
	void signal(semaphore* S) {
		S->value++;
		if (this->roleFlag == 1) 					//生产者释放对盘子的访问权 
		{
			if (this->pc == 5)
			{
				cout << this->name << "   成功,生产者释放缓冲池使用权,signal(Mutex)" << endl;
			}
			else if (this->pc == 6) {
				cout << this->name << "   成功,生产者通知其他进程,signal(Full)" << endl;
			}
		}
		else if (this->roleFlag == 0) 				//消费者释放对盘子的访问权 
		{
			if (this->pc == 4)
			{
				cout << this->name << "   成功,消费者释放缓冲使用权,signal(Mutex)" << endl;
			}
			else if (this->pc == 5) {
				cout << this->name << "   成功,消费者通知其他进程,signal(Full)" << endl;
			}
		}

		if (S->value <= 0)
		{
			wakeup(S->list);
		}
		this->pc++;
		if ((this->roleFlag == 0 && this->pc == 6) || (this->roleFlag == 1 && this->pc == 7)) {
			cout << "已经完成一个进程===================================================================================" << this->name << endl;
			cout << "name:" << this->name << "code:" << this->code << "pc:" << this->pc << "state:" << this->state << endl;
			this->pc = 1;
		}
	}

};
PCB process[processNum];   //进程集合,roleFlag属性 1生产者,0消费者

PCB* wakeup(queue<PCB*>*& list) {
	PCB* p = (*list).front();
	int code = p->code;
	process[code].state = 1;		//进程置为就绪态
	if (process[code].roleFlag == 1) { //生产者
		if (process[code].pc == 2)
		{
			cout << process[code].name << "   被唤醒,发现缓冲池不是满的" << "  缓冲池中食物数量" << food << "Full值" << Full.value << endl;
		}
		if (process[code].pc == 3)
		{
			cout << process[code].name << "   被唤醒,发现没有其他进程占有缓冲池" << "互斥变量" << Mutex.value << endl;
			mutex_c = 1;
		}
	}
	if (process[code].roleFlag == 0)    //消费者
	{
		if (process[code].pc == 1)
		{
			cout << process[code].name << "   被唤醒,发现缓冲池中有食物" << "  食物数量" << food << "  Full值" << Full.value << endl;
		}
		if (process[code].pc == 2)
		{
			cout << process[code].name << "   被唤醒,发现没有其他进程占有缓冲池" << "  互斥变量" << Mutex.value << endl;
		}

	}
	process[code].pc++;
	(*list).pop();               //删除队首进程
	return p;
}

PCB* block(queue<PCB*>*& list, PCB* pcb) {
	(*list).push(pcb);
	PCB* cur = list->front();
	process[pcb->code].state = 0;       //进程设置为阻塞态
	return pcb;
}




/*生产者消费者类*/
class PandC {
private:
	int in, out;//指向有产品的下标
	int count;//缓冲区的产品数
	int buffer[N];//缓冲区
	int mutex;//互斥信号量
	int  empty, full;//判断缓冲区是否为空或者满
public:
	/*初始化,构造生产者消费者*/
	PandC() {
		in = 0; out = 0; count = 0;
		empty = N; full = 0; mutex = 1;
		for (int i = 0; i < N; i++)
			buffer[i] = 0;
	}

	/*生产者生产进程*/
	void Producer(PCB* pro) {
		int tim = rand() % 10 + 1;
		switch (pro->pc)
		{
		case 1:							//1 生产物品	
			cout << pro->name << "   生产者正在生产食物" << "所需时间" << tim << "秒" << endl;
			Sleep(tim * 100);//其实没有等待足够的tim,缩小了十倍,比如假设等8秒实际等了800毫秒
			/// <summary>
			/// 生产者生产后如果不能放入缓冲池,那么这份食物就拿在手里,然后把该线程挂到阻塞队列中。
			/// </summary>
			/// <param name="pro"></param>
			pro->pc++;
			cout << pro->name << "   生产者生产时间" << tim << "秒" << "缓冲池中食物数量" << food << "个" << endl;
			break;
		case 2:							//2 申请空盘子 
			Sleep(350);
			cout << pro->name << "   生产者查看缓冲池是否满了wait(empty)" << endl;
			pro->wait(&Empty);
			break;
		case 3:							//3 申请的盘子访问权 
			Sleep(350);
			cout << pro->name << "   生产者查看是否有人使用缓冲队列wait(mutex)" << endl;
			pro->wait(&Mutex);
			break;
		case 4:					       //4 放入食物	
			Sleep(350);
			food++;
			cout << pro->name << "   放入食物" << "缓冲池中有食物" << food << "个" << "  Full值为(二值不一致说明由消费者进程堵塞)" << Full.value << endl;
			pro->pc++;
			break;
		case 5:						   //5 释放对盘子的访问权
			Sleep(350);
			cout << pro->name << "   释放缓冲队列控制权signal(mutex)" << endl;
			pro->signal(&Mutex);
			break;
		case 6:
			//6 水果已经放入盘子 ,通知两个消费者		  
			Sleep(350);
			cout << pro->name << "   已经完成生产过程通知消费者signal(full)" << endl;
			pro->signal(&Full);
			pro->pc = 1;
			break;
		}
	}

	/*消费者消费*/
	void Consumer(PCB* pro) {
		switch (pro->pc)
		{
		case 1:					 //1 申请从盘子中拿水果
			Sleep(350);
			cout << pro->name << "  消费者提出申请拿走食物wait(full)" << "  当前缓冲池中食物数量" << food << "当前full值" << Full.value << " 二者不一致表示有生产者虽然放置了食物但是没有signal操作完毕" << endl;
			/*注意:这里放置sleep是假设下几个时间片执行的时候这里刚好生产完毕,简化了操作,抽象理解,这里只是简单模拟,实际上其他时间片结束后这里才生产完毕*/
			pro->wait(&Full);
			break;
		case 2:					//2 申请盘子的访问权 
			Sleep(350);
			cout << pro->name << "消费者获得拿走食物的申请wait(mutex)" << endl;
			pro->wait(&Mutex);
			break;
		case 3:					//3 从盘子里取水果

			Sleep(350);
			food--;
			cout << pro->name << "   消费者拿走食物" << endl;
			pro->pc++;

			break;
		case 4:					//4 释放对盘子的访问权
			Sleep(350);
			cout << pro->name << "   消费者释放访问权signal(mutex)" << endl;
			pro->signal(&Mutex);
			break;
		case 5:					//5 已经从盘子里取走水果,通知父亲放水果 
			Sleep(350);
			cout << pro->name << "   消费者拿走食物signal(empty)" << endl;;
			pro->signal(&Empty);
			pro->pc = 1;
			break;
		}

	}
};


void initProcess(int pN, int cN)//初始化函数  pN生产者个数,cN消费者个数
{
	int i = 0;
	for (; i < pN; i++) {
		process[i].name = to_string(i + 1) + "号生产者进程";
		process[i].roleFlag = 1;
		process[i].state = 1;//就绪状态 
		process[i].pc = 1;//第一步 
		process[i].code = i;
	}
	for (; i < cN + pN; i++)
	{

		process[i].name = to_string(i + 1) + "号消费者进程";
		process[i].roleFlag = 0;
		process[i].state = 1;//就绪状态 
		process[i].pc = 1;//第一步 
		process[i].code = i;
	}

}


int main() {
	int i = 0;//时间片执行次数
	/*随机执行生产者生产还是消费者消费*/
	int ci = 0;
	printf(">>>>>>>>>>>>>>>>>>>>>>>>>(一下所有数字都是正整数)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
	printf("请输入时间片执行次数,用于模拟多进程,请输入较大的值如(50):");
	cin >> ci;
	cout << "请输入生产者个数,消费者个数,空格分隔,输入1 1表示单消费者和单生产者模型";
	int pN = 0, cN = 0;
	cin >> pN >> cN;
	printf("执行时间片%d次\n", ci);
	printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n\n\n");
	initProcess(pN, cN);
	printf(">>>>>>>>>>>>>>>>>>>>Process begins......>>>>>>>>>>>>>>>>>>>>>>>\n");
	PandC factory;
	PCB* cur;
	int a = 0;
	//Mutex.value = pN + cN - 1;
	//定义均匀分布对象,均匀分布区间(a,b)为(0,pN+cN)
	uniform_int_distribution<int> uid{ 0,pN + cN - 1 };
	//定义随机数种子
	random_device rd;
	//定义默认随机数生成器
	default_random_engine dre{ rd() };
	do {
		//srand(time(NULL));
		//a = rand() % (pN+cN)+1;
		a = uid(dre);
		cur = &process[a];
		cout << cur->name << ":" << "full:" << Full.value << " mutex:" << Mutex.value << " empty:" << Empty.value << " code:" << cur->code << " pc:" << cur->pc << " state:" << cur->state << endl;
		if (!cur->state) {
			continue;
		}
		if (cur->roleFlag == 1) {
			factory.Producer(cur);

		}
		else {
			factory.Consumer(cur);

		}
		i++;
		cout << "时间片执行次数============================" << i << endl;
	} while (i != ci);
	cout << "时间片执行" << ci << "次" << "最终执行结果:" << endl;
	cout << "full:" << Full.value << endl;
	cout << "empty:" << Empty.value << endl;
	cout << "mutex:" << Mutex.value << endl;
	cout << "food:" << food << endl;
	return 0;
}

老师:“你们就简单实现以下就行”

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值