C语言——生产者消费者问题

百度文献查看原文

核心代码:

#include<stdio.h>
#include<time.h>
#include<stdlib.h>
#include<string.h>
#include<windows.h>
#define dataBufferSize  2        //缓冲区数目
#define processNum 4            //进程数量(生产者、消费者进程总数目)
typedef struct Seamphore          //信号量
{
    
           
int value;            //信号量的值
int *pcq;            //信号量队列指针
} Seamphore;
int producerCongestionQueue[processNum];    //等待信号量empty的阻塞队列
int consumerCongestionQueue[processNum];    //等待信号量full的阻塞队列
int shareCongestionQueue[processNum];        //等待信号量mutex的阻塞队列
Seamphore empty={
    
    dataBufferSize,producerCongestionQueue}; // empty:空缓冲区数目
Seamphore full={
    
    0,consumerCongestionQueue};  // full:缓冲区内可用的产品
Seamphore mutex={
    
    1,shareCongestionQueue};    //mutex:互斥信号量
struct DataBuffer          //缓冲区
{
    
               
int buffer[dataBufferSize];   
int count;                //当前产品数量
}dataBuffer;
typedef struct Process          //进程PCB
{
    
    
char name[10];                //进程名
int roleFlag;                    //进程类型(1: 生产者  0: 消费者)
int currentState;              //进程状态(1: 就绪态  0: 阻塞态)
int currentStep;              //断点
int data;                        //临时数据
int code;                        //进程编号
}Process;
Process process[processNum];    //进程集合
void moveDataForward()
{
    
           
int i;
for (i = 0; i <dataBuffer.count; i++)
dataBuffer.buffer[i] = dataBuffer.buffer[i+1];
}
void push(int data)      //产品送入缓冲区
{
    
               
dataBuffer.buffer[dataBuffer.count++] = data;
}
int pop()            //从缓冲区取出产品
{
    
                           
int data = dataBuffer.buffer[0];
dataBuffer.count--;           
moveDataForward();
return data;
}
void initProcess() {
    
                //初始化进程集合
int i;
char digitTemp[5];
srand(time(NULL));
for (i = 0; i <processNum; i++) {
    
    
process[i].roleFlag = rand()%2;            // 随机指定当前进程为生产者或消费者
if (process[i].roleFlag)
strcpy(process[i].name, "生产者");
else
strcpy(process[i].name, "消费者");
strcat(process[i].name, itoa(i+1, digitTemp, 10));
process[i].currentState = 1;
process[i].currentStep = 1;
process[i].code = i + 1;
producerCongestionQueue[i] = 0;
consumerCongestionQueue[i] = 0;
shareCongestionQueue[i] = 0;
}
}
void wakeup(int *pcq) {
    
                        //唤醒进程
int code = pcq[0] - 1;                //取出队首进程
process[code].currentState = 1;        //进程置为就绪态
//当进程被唤醒后继续执行任务
if (process[code].roleFlag == 1) {
    
            //生产者
if (process[code].currentStep == 2) {
    
    
printf("%20s: 该进程被唤醒!申请空缓冲区成功!\n", process[code].name);
} else if (process[code].currentStep == 3) {
    
    
printf("%20s: 该进程被唤醒!申请访问缓冲区成功!\n", process[code].name);
}
} else if (process[code].roleFlag == 0) {
    
        //消费者
if (process[code].currentStep == 1) {
    
    
process[code].data = pop();
printf("%20s: 该进程被唤醒!申请取产品%d成功!\n", process[code].name, process[code].data);
} else if (process[code].currentStep == 2) {
    
    
printf("%20s: 该进程被唤醒!申请访问缓冲区成功!\n", process[code].name);
}       
}
process[code].currentStep++;
for (int i = 1; (i <processNum) && (pcq[i] != 0); i++) {
    
            //删除队首进程
pcq[i-1] = pcq[i];
if (pcq[i-1] >processNum) {
    
    
pcq[i-1] = 0;
}
}  
}
void sleep(int pcq[], int code) {
    
                //阻塞进程   
int i;
process[code-1].currentState = 0;            //进程置为阻塞态
for (i = 0; i <processNum; i++) {
    
    
if (!pcq[i]) {
    
    
pcq[i] = code;
break;
}
}
}
void P(Seamphore *s, Process *p) {
    
                    //模拟P操作
s->value -= 1;
if (s->value>= 0) {
    
                           
if (p->roleFlag == 1) {
    
                        //生产者
if (p->currentStep == 2) {
    
    
printf("%20s: 申请空缓冲区成功!\n", p->name);
} else if (p->currentStep == 3) {
    
    
printf("%20s: 申请访问缓冲区成功!\n", p->name);
}
} else if (p->roleFlag == 0) {
    
                //消费者
if (p->currentStep == 1) {
    
    
printf("%20s: 申请取出产品成功!\n", p->name);
} else if (p->currentStep == 2) {
    
    
printf("%20s: 申请访问缓冲区成功!\n", p->name);
}
}       
p->currentStep++;                        //下一步
} else if (s->value < 0) {
    
                   
if (p->roleFlag == 1) {
    
                        //生产者
if (p->currentStep == 2) {
    
    
printf("%20s: 无空缓冲区, 该进程被阻塞!\n", p->name);
} else if (p->currentStep == 3) {
    
    
printf("%20s: 其他进程正在访问缓冲区, 该进程被阻塞!\n", p->name);
}
} else if (p->roleFlag == 0) {
    
                //消费者
if (p->currentStep == 1) {
    
    
printf("%20s: 无产品可取, 该进程被阻塞!\n", p->name);
} else if (p->currentStep == 2) {
    
    
printf("%20s: 其他进程正在访问缓冲区, 该进程被阻塞!\n", p->name);
}
}
sleep(s->pcq, p->code);        //阻塞进程       
}
}
void V(Seamphore *s, Process *p) {
    
                //模拟V操作
s->value += 1;
if (p->roleFlag == 1) {
    
                        //生产者
if (p->currentStep == 5) {
    
    
printf("%20s: 释放缓冲区访问权!\n", p->name);
} else if (p->currentStep == 6) {
    
    
printf("%20s: 产品已送入缓冲区,产品数量增加!\n", p->name);
}
} else if (p->roleFlag == 0) {
    
                //消费者
if (p->currentStep == 4) {
    
    
printf("%20s: 释放缓冲区访问权!\n", p->name);
} else if (p->currentStep == 5) {
    
    
printf("%20s: 产品已取出,空缓冲区数量增加!\n", p->name);
}
}
if (s->value<= 0) {
    
    
wakeup(s->pcq);       
}
p->currentStep++;           
}
void produce(Process *p) {
    
                //模拟生产者进程
switch (p->currentStep) {
    
    
case 1:                                                            //1 生产产品
p->data = rand()%1000;
printf("%20s: 生产一个产品%d!\n", p->name, p->data);
p->currentStep++;
break;
case 2:                                                            //2 申请空缓冲区
P(&empty, p);
break;
case 3:                                                            //3 申请访问缓冲区
P(&mutex, p);
break;
case 4:                                                            //4 将产品送入缓冲区
push(p->data);
printf("%20s: 将产品%d正送入缓冲区!\n", p->name, p->data);
p->currentStep++;
break;
case 5:                                                            //5 释放缓冲区访问权
V(&mutex, p);
break;
case 6:                                                            //6 产品已送入缓冲区,产品数量加1
V(&full, p);
p->currentStep = 1;
break;
}
}
void consume(Process *p) {
    
                    //模拟消费者进程
switch (p->currentStep) {
    
    
case 1:                                                            //1 申请从缓冲区取出产品
P(&full, p);
break;
case 2:                                                            //2 申请访问缓冲区
P(&mutex, p);
break;
case 3:                                                            //3 从缓冲区中取出产品
p->data = pop();
printf("%20s: 从缓冲区中正取出产品%d!\n", p->name, p->data);
p->currentStep++;
break;
case 4:                                                            //4 释放缓冲区访问权
V(&mutex, p);
break;
case 5:                                                    //5 已从缓冲区取出一个产品,空缓冲区数量加1
V(&empty, p);
break;
case 6:                                                            //6 消费产品
printf("%20s: 消费产品%d!\n", p->name, p->data);
p->currentStep = 1;
break;
}
}
void rr() {
    
                //模拟进程调度
Process *p;
while(1) {
    
    
p = &process[rand()%processNum];        //随机选取进程集合内某一进程
if (!p->currentState) {
    
                        //选取的进程若为阻塞态,重新选取其它可执行进程
continue;
}
if (p->roleFlag) {
    
                //1: 生产者  0: 消费者
produce(p);
} else {
    
    
consume(p);
}   
Sleep(100);
}
}
void deal() {
    
    
printf("\t\t生产者消费者算法模拟\n\n");
initProcess();
rr();
}
int main () {
    
    
deal();
return 0;
}

猜你喜欢

转载自blog.csdn.net/GodOuO/article/details/105952713