介绍
按下空格暂停。
C++代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <windows.h>
#include <conio.h>
#include <queue>
#define PDC 0 //生产者
#define CSM 1 //消费者
using namespace std;
typedef pair<int,int> PII; //第一个元素是身份,第二个元素是id
const int N = 1005; //生产者消费者最大数目
int pdc_num,csm_num,n; //生产者数目,消费者数目,缓冲块数目
int empty; //初值为 n,指示空缓冲块数目
int full; //初值为 0,指示满缓冲块数目
int mutex; //初值为 1,用于实现临界区互斥
int current = 0; // producer运行加1,consumer运行减1
int flag[2][N]; //0为运行态,1为阻塞态
int state[2][N]; //运行态的状态,用于时间片轮转。
bool fstop; //暂停标志
queue<PII> q_empty,q_full,q_mutex; //队列存阻塞的进程
//参数:信号量,可能需要阻塞的进程(身份和序号),队列
int P(int &S, PII pcb, queue<PII> &q) {
S = S-1;
if(S<0) { //阻塞进程
flag[pcb.first][pcb.second] = 1; //阻塞
q.push({pcb.first,pcb.second}); //扔进队列
}
}
//参数:信号量,队列
int V(int &S, queue<PII> &q) {
S = S+1;
if(S<=0) { //唤醒进程
if(!q.empty()) {
PII pcb = q.front();q.pop(); //取队首元素
flag[pcb.first][pcb.second] = 0; //唤醒
}
}
}
void produce(int id) { //第id个生产者生产
//如果阻塞,直接返回,该轮不执行程序。
if(flag[PDC][id]) return;
switch(state[PDC][id]) {
case 0: P(empty,{0,id},q_empty); break;
case 1: P(mutex,{0,id},q_mutex); break;
case 2: current++; break;
case 3: V(mutex,q_mutex); break;
case 4: V(full,q_full); break;
}
state[PDC][id]++;
if(state[PDC][id]==5)state[PDC][id]=0;
printf("第%d个生产者\t产品数:%d\tempty:%2d\tfull:%2d\t\tmutex:%2d",
id,current,empty,full,mutex);
if(flag[PDC][id]) cout << " \t阻塞了";
cout << endl;
}
void consume(int id) { //第id个消费者消费
//如果阻塞,直接返回,该轮不执行程序。
if(flag[CSM][id]) return;
switch(state[CSM][id]) {
case 0: P(full,{1,id},q_full); break;
case 1: P(mutex,{1,id},q_mutex); break;
case 2: current--; break;
case 3: V(mutex,q_mutex); break;
case 4: V(empty,q_empty); break;
}
state[CSM][id]++;
if(state[CSM][id]==5)state[CSM][id]=0;
printf("第%d个消费者\t产品数:%d\tempty:%2d\tfull:%2d\t\tmutex:%2d",
id,current,empty,full,mutex);
if(flag[CSM][id]) cout << " \t阻塞了";
cout << endl;
}
void KeyScan() {
while (kbhit()) { //如果有按键按下
int key = getch();//不回显的获取按键
if(key == 32) { //空格暂停或恢复运行
fstop = !fstop;
}
}
}
int main() {
printf("请输入生产者数目 消费者数目 缓冲块数量\n");
cin >> pdc_num >> csm_num >> n;
//初始化
mutex = 1, empty = n, full = 0;
//run
while(true) {
//生产消费
if(!fstop)for(int i = 1; i <= pdc_num; i++) produce(i);
if(!fstop)for(int i = 1; i <= csm_num; i++) consume(i);
KeyScan(); //按键扫描
}
return 0;
}
运行效果
输入
运行中
暂停