利用记录型信号量解决生产者-消费者问题,C++版



#include <iostream>
#include <string.h>
#include <stdio.h> 
#include <ctype.h> 
#include <stdlib.h> 
#include <math.h>
#include <malloc.h>
#define  MAX   50
#define  OK  1
#define  ERROR   0
int empty;//全局变量
int mutex;
int sa;
int sb;


typedef struct process{
char name[10];
char pubsignal[10];
char prisignal1[10];
char prisignal2[10];
char style;//P或者C
struct process *next;
}process,*queueptr;


typedef struct{
queueptr front;
queueptr rear;
}linkqueue;


void Initqueue(linkqueue &Q){
Q.front=Q.rear=(queueptr)malloc(sizeof(process));
if (!Q.front) exit (OVERFLOW);
Q.front->next=NULL;
Q.front->name[0]=0;//赋初值
Q.front->prisignal1[0]=0;
Q.front->prisignal2[0]=0;
Q.front->pubsignal[0]=0;
Q.front->style=0;
return;
}


void Enqueue(linkqueue &Q,char a[],char b[],char c[],char d[],char e){
queueptr p;
p=(queueptr)malloc(sizeof(process));
if (!p) exit (OVERFLOW);
for (int i=0;i<10;i++)
{
p->name[i]=a[i];
}
    for (int j=0;j<10;j++)
{
p->pubsignal[j]=b[j];
}
for (int x=0;x<10;x++)
{
p->prisignal1[x]=c[x];
}
for (int y=0;y<10;y++)
{
p->prisignal2[y]=d[y];
}
p->style=e;
p->next=NULL;
Q.rear->next=p;
Q.rear=p;
return;
}


void Dequeue(linkqueue &Q){
if (Q.front==Q.rear) return;
queueptr p;
p=Q.front->next;
Q.front->next=p->next;
if (Q.rear==p) Q.rear=Q.front;
delete (p);
return;
}


void printprocess(linkqueue &Q)
{
   queueptr p;
   p=Q.front->next;
   do{
  printf("--------------------------------------------------------------------------------\n");
  printf("进程名%s  互斥信号量%s  私有信号量%s  私有信号量%s  进程类型%c\n",p->name,p->pubsignal,p->prisignal1,p->prisignal2,p->style);
  printf("--------------------------------------------------------------------------------\n");
  p=p->next;
   }while (p!=NULL);
}


void P(char a[],linkqueue &excutiveQ,linkqueue &mutexQ,linkqueue &emptyQ,linkqueue &saQ,linkqueue &sbQ)
{
if (strcmp("mutex",a)==0)
{
mutex--;
if (mutex<0)//进程挂起,到信号量mutex的队尾排队
{   
            //mutex=0;//强制置零,冒险?
printf("信号量mutex不足,<%s>到信号量mutex队尾排队\n",excutiveQ.front->next->name);
Enqueue(mutexQ,excutiveQ.front->next->name,excutiveQ.front->next->pubsignal,excutiveQ.front->next->prisignal1,excutiveQ.front->next->prisignal2,excutiveQ.front->next->style);
Dequeue(excutiveQ); 


}
}
    if (strcmp("empty",a)==0)
{
empty--;
if (empty<0)//进程挂起,到信号量empty的队尾排队
{
           
//empty=0;
printf("信号量empty不足,<%s>到信号量empty队尾排队\n",excutiveQ.front->next->name);
Enqueue(emptyQ,excutiveQ.front->next->name,excutiveQ.front->next->pubsignal,excutiveQ.front->next->prisignal1,excutiveQ.front->next->prisignal2,excutiveQ.front->next->style);
Dequeue(excutiveQ); 
   

}
}
     if (strcmp("sa",a)==0)
{
sa--;
if (sa<0)//进程挂起,到信号量sa的队尾排队
{
            //sa=0;

printf("信号量sa不足,<%s>到信号量sa队尾排队\n",excutiveQ.front->next->name);
Enqueue(saQ,excutiveQ.front->next->name,excutiveQ.front->next->pubsignal,excutiveQ.front->next->prisignal1,excutiveQ.front->next->prisignal2,excutiveQ.front->next->style);
Dequeue(excutiveQ);


}
}
    if (strcmp("sb",a)==0)
{
sb--;
if (sb<0)//进程挂起,到信号量sb的队尾排队
{
            //sb=0;

printf("信号量sb不足,<%s>到信号量sb队尾排队\n",excutiveQ.front->next->name);
Enqueue(sbQ,excutiveQ.front->next->name,excutiveQ.front->next->pubsignal,excutiveQ.front->next->prisignal1,excutiveQ.front->next->prisignal2,excutiveQ.front->next->style);
Dequeue(excutiveQ); 


}
}
}


void V(char a[],linkqueue &excutiveQ,linkqueue &mutexQ,linkqueue &emptyQ,linkqueue &saQ,linkqueue &sbQ)
{
if (strcmp("mutex",a)==0)
{

mutex++;
if (mutex>0)//进程唤醒,到执行进程队尾排队
{
            if (mutexQ.front->next!=NULL){
printf("信号量mutex+1,mutex队列中的<%s>到执行进程队尾排队\n",mutexQ.front->next->name);
Enqueue(excutiveQ,mutexQ.front->next->name,mutexQ.front->next->pubsignal,mutexQ.front->next->prisignal1,mutexQ.front->next->prisignal2,mutexQ.front->next->style);
Dequeue(mutexQ);}
}
}
    else if (strcmp("empty",a)==0)
{

empty++;
if (empty>0)//进程唤醒,到执行队尾排队
{
            if (emptyQ.front->next!=NULL){
printf("信号量empty+1,empty队列中的<%s>到执行进程队尾排队\n",emptyQ.front->next->name);
Enqueue(excutiveQ,emptyQ.front->next->name,emptyQ.front->next->pubsignal,emptyQ.front->next->prisignal1,emptyQ.front->next->prisignal2,emptyQ.front->next->style);
Dequeue(emptyQ);}
}
}
   else  if (strcmp("sa",a)==0)
{
 
sa++;
if (sa>0)//进程唤醒,到执行队尾排队
{
            if (saQ.front->next!=NULL){//队列不为空
printf("信号量sa+1,sa队列中的<%s>到执行进程队尾排队\n",saQ.front->next->name);
Enqueue(excutiveQ,saQ.front->next->name,saQ.front->next->pubsignal,saQ.front->next->prisignal1,saQ.front->next->prisignal2,saQ.front->next->style);
Dequeue(saQ);}
}
}
   else if (strcmp("sb",a)==0)
{

sb++;
if (sb>0)//进程唤醒,到执行队尾排队
{
            if (sbQ.front->next!=NULL){
printf("信号量sb+1,sb队列中的<%s>到执行进程队尾排队\n",mutexQ.front->next->name);
Enqueue(excutiveQ,sbQ.front->next->name,sbQ.front->next->pubsignal,sbQ.front->next->prisignal1,sbQ.front->next->prisignal2,sbQ.front->next->style);
Dequeue(sbQ);}
}
}
}






void excutiveproducer1(linkqueue &excutiveQ,linkqueue &mutexQ,linkqueue &emptyQ,linkqueue &saQ,linkqueue &sbQ)
{
while (1)
{
printf("-----------------现在执行的进程是<%s>-----------------\n",excutiveQ.front->next->name);
P("empty",excutiveQ,mutexQ,emptyQ,saQ,sbQ);
   printf("P(empty)之后,mutex=%d,empty=%d,sa=%d,sb=%d\n",mutex,empty,sa,sb);
if (empty<0) 
{   empty=0;
break;  }
P("mutex",excutiveQ,mutexQ,emptyQ,saQ,sbQ);
printf("P(mutex)之后,mutex=%d,empty=%d,sa=%d,sb=%d\n",mutex,empty,sa,sb);
if (mutex<0)  break;
if (empty>=0&&mutex>=0)
{
printf("-------------------------------生产%s-------------------------------\n",excutiveQ.front->next->prisignal2);
V("sa",excutiveQ,mutexQ,emptyQ,saQ,sbQ);
   printf("V(sa)之后,mutex=%d,empty=%d,sa=%d,sb=%d\n",mutex,empty,sa,sb);
V("mutex",excutiveQ,mutexQ,emptyQ,saQ,sbQ);
   printf("V(mutex)之后,mutex=%d,empty=%d,sa=%d,sb=%d\n",mutex,empty,sa,sb);
}
}
  
return;
}


void excutiveproducer2(linkqueue &excutiveQ,linkqueue &mutexQ,linkqueue &emptyQ,linkqueue &saQ,linkqueue &sbQ)
{
while (1)
{
printf("-----------------现在执行的进程是<%s>-----------------\n",excutiveQ.front->next->name);
P("empty",excutiveQ,mutexQ,emptyQ,saQ,sbQ);
printf("P(empty)之后,mutex=%d,empty=%d,sa=%d,sb=%d\n",mutex,empty,sa,sb);
if (empty<0) 
{
empty=0;
break;}
P("mutex",excutiveQ,mutexQ,emptyQ,saQ,sbQ);
printf("P(mutex)之后,mutex=%d,empty=%d,sa=%d,sb=%d\n",mutex,empty,sa,sb);
if (mutex<0) break;
if (empty>=0&&mutex>=0)
{
printf("-------------------------------生产%s-------------------------------\n",excutiveQ.front->next->prisignal2);
    V("sb",excutiveQ,mutexQ,emptyQ,saQ,sbQ);
   printf("V(sb)之后,mutex=%d,empty=%d,sa=%d,sb=%d\n",mutex,empty,sa,sb);
V("mutex",excutiveQ,mutexQ,emptyQ,saQ,sbQ);
   printf("V(mutex)之后,mutex=%d,empty=%d,sa=%d,sb=%d\n",mutex,empty,sa,sb);
}
}
return;

}


void excutiveconsumer1(linkqueue &excutiveQ,linkqueue &mutexQ,linkqueue &emptyQ,linkqueue &saQ,linkqueue &sbQ)
{
while (1)
{
printf("-----------------现在执行的进程是<%s>-----------------\n",excutiveQ.front->next->name);
P("sa",excutiveQ,mutexQ,emptyQ,saQ,sbQ);
printf("P(sa)之后,mutex=%d,empty=%d,sa=%d,sb=%d\n",mutex,empty,sa,sb);
if (sa<0) 
{
sa=0;
break;}
P("mutex",excutiveQ,mutexQ,emptyQ,saQ,sbQ);
printf("P(mutex)之后,mutex=%d,empty=%d,sa=%d,sb=%d\n",mutex,empty,sa,sb);
if (mutex<0) break;
if (sa>=0&&mutex>=0)
{
printf("-------------------------------消费%s-------------------------------\n",excutiveQ.front->next->prisignal2);
   V("empty",excutiveQ,mutexQ,emptyQ,saQ,sbQ);
   printf("V(empty)之后,mutex=%d,empty=%d,sa=%d,sb=%d\n",mutex,empty,sa,sb);
V("mutex",excutiveQ,mutexQ,emptyQ,saQ,sbQ);
   printf("V(mutex)之后,mutex=%d,empty=%d,sa=%d,sb=%d\n",mutex,empty,sa,sb);
}
}
  return;
}


void excutiveconsumer2(linkqueue &excutiveQ,linkqueue &mutexQ,linkqueue &emptyQ,linkqueue &saQ,linkqueue &sbQ)
{
while (1)
{
printf("-----------------现在执行的进程是<%s>-----------------\n",excutiveQ.front->next->name);
P("sb",excutiveQ,mutexQ,emptyQ,saQ,sbQ);
printf("P(sb)之后,mutex=%d,empty=%d,sa=%d,sb=%d\n",mutex,empty,sa,sb);
if (sb<0) 
{
sb=0;
break;}
P("mutex",excutiveQ,mutexQ,emptyQ,saQ,sbQ);
printf("P(mutex)之后,mutex=%d,empty=%d,sa=%d,sb=%d\n",mutex,empty,sa,sb);
if (mutex<0) break;
if (sb>=0&&mutex>=0)
{
printf("-------------------------------消费%s-------------------------------\n",excutiveQ.front->next->prisignal2);
   V("empty",excutiveQ,mutexQ,emptyQ,saQ,sbQ);
   printf("V(empty)之后,mutex=%d,empty=%d,sa=%d,sb=%d\n",mutex,empty,sa,sb);
V("mutex",excutiveQ,mutexQ,emptyQ,saQ,sbQ);
   printf("V(mutex)之后,mutex=%d,empty=%d,sa=%d,sb=%d\n",mutex,empty,sa,sb);
}
}
  return;
}






void excuteprocess(linkqueue &excutiveQ,linkqueue &mutexQ,linkqueue &emptyQ,linkqueue &saQ,linkqueue &sbQ)
{
    if (strcmp(excutiveQ.front->next->name,"producer1")==0)//队列中第一个结点是空,去第二个结点来判断
{
excutiveproducer1(excutiveQ,mutexQ,emptyQ,saQ,sbQ);
}
    else  if (strcmp(excutiveQ.front->next->name,"producer2")==0)
{

excutiveproducer2(excutiveQ,mutexQ,emptyQ,saQ,sbQ);
}
    else  if (strcmp(excutiveQ.front->next->name,"consumer1")==0)
{

excutiveconsumer1(excutiveQ,mutexQ,emptyQ,saQ,sbQ);
}
    else  if (strcmp(excutiveQ.front->next->name,"consumer2")==0)
{

excutiveconsumer2(excutiveQ,mutexQ,emptyQ,saQ,sbQ);
}


}






























void main()
{
empty=2;
    mutex=2;
    sa=0;
    sb=0;
linkqueue excutiveQ;
linkqueue emptyQ;
linkqueue saQ;
linkqueue sbQ;
linkqueue mutexQ;
Initqueue(excutiveQ);//就绪队列
    Initqueue(emptyQ);//信号量empty的等待队列
Initqueue(saQ);//信号量sa的等待队列
Initqueue(sbQ);//信号量sb的等待队列
Initqueue(mutexQ);//信号量mutex的等待队列
   
    Enqueue(excutiveQ,"producer1","mutex","empty","sa",'P');
    Enqueue(excutiveQ,"producer2","mutex","empty","sb",'P');
    Enqueue(excutiveQ,"consumer1","mutex","empty","sa",'C');
Enqueue(excutiveQ,"consumer2","mutex","empty","sb",'C');
  
//excutiveQ.front=excutiveQ.front->next;//去掉队列中的第一个结点
    

printf("--------------------------------------------------------------------------------\n");


int flag;

do
{
printf("1.进程信息     2.开始    3.结束\n");
scanf("%d",&flag);
if (flag==1)
{
printprocess(excutiveQ);
}
    
        if (flag==2)//执行进程
{
printf("---------->初始信号量mutex=%d,empty=%d,sa=%d,sb=%d<------------\n",mutex,empty,sa,sb);



 excuteprocess(excutiveQ,mutexQ,emptyQ,saQ,sbQ);
}
}while (flag!=3);


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值