有一个盘子,可以放5个水果(苹果or桔子)。父亲每次向盘子随机放入一个水果(苹果or桔子),父亲放入水果的次数不少于11次。儿子只吃桔子,女儿只吃苹果。请编程使用信号量机制模拟解决此进程同步问题。打印信息包括盘子的情况、调度的情况以及父亲、儿子或者女儿执行的操作。
一步一步来,一切就水到渠成了
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
struct fruit{
int id;//0代表没水果,1代表桔子,2代表苹果
struct fruit *next;
};
int f=1,d=1,s=1;//三个是父亲女儿儿子的缩写,代表三个人是否被阻塞
struct fruit *head=(struct fruit*)malloc(sizeof(struct fruit));
struct fruit *initfruit(){//初始化队列,5个结构体代表5个水果的状态
head->id=0;
struct fruit *p,*q;
q=head;
for(int i=0;i<4;i++){
p=(struct fruit*)malloc(sizeof(struct fruit));
q->next=p;
p->id=0;//一开始盘子里的没水果,id全部为0
q=p;
}
p->next=head;
return head;
}
void putfruit(int i){//放水果操作 ,有空位则放水果,没有空位则阻塞爸爸
struct fruit *p;
p=head;
int flag=1,n=5,count=0;//flag用于限制只能进行放一个水果,n用于限制只能循环一遍
while(n--&&flag){//一共有5个节点,现在p指向第一个节点,所以遍历全部节点只需要4步,n取值<5保证不会进行多次无效循环
if(p->id==0){//这个节点没有放水果
if(i==1){
p->id=1;
printf("放入一个桔子\n");
if(s==0){//如果儿子是属于阻塞态的,则唤醒儿子
s=1;
printf("儿子被唤醒\n");
}
flag=0;
}
if(i==2){
p->id=2;
printf("放入一个苹果\n");
if(d==0){//如果儿子是属于阻塞态的,则唤醒儿子
d=1;
printf("女儿被唤醒\n");
}
flag=0;
}
}
else{
count++;
p=p->next;
}
}
count++;//用来记盘子里水果数量
if(count==5){
f=0;//如果p->next的id是0则代表p->next是head说明盘子已经满了,这时需要阻塞爸爸
printf("父亲被阻塞\n");
}
}
void searchfruit(int i){
struct fruit *p;
p=head;
int flag=1,n=4;
while(n--&&flag){
if(i==1){
if(p->id==1){
flag=0;//一次只能吃一个水果
p->id=0;
printf("吃一个桔子\n");
}
else
p=p->next;
}
if(i==2){
if(p->id==2){
flag=0;
p->id=0;
printf("吃一个苹果\n");
}
else
p=p->next;
}
}
if(flag==1){//判断是否吃过水果
if(i==1){
s=0;
printf("儿子被阻塞\n");
}
if(i==2){
d=0;
printf("女儿被阻塞\n");
}
}
if(flag==0&&f==0){
f=1;
printf("唤醒爸爸\n");
}
}
void printfruit(){
struct fruit *p;
p=head;
int n=5;
printf("盘子现在的状态:|");
while(n--){
if(p->id==0){
printf(" |");
}
else if(p->id==1){
printf("O|");
}
else{
printf("A|");
}
p=p->next;
}
printf("\n");
}
int main(){
int n,flag=0,a,b;//a,b代表取随机数
printf("Please input scheduling count:");
scanf("%d",&n);
struct fruit *p,*pu;//*pu用于放入水果
p=initfruit();
srand((unsigned)time(0));
while(n--){//能抢资源的前提是没有被阻塞
a=rand()%3;//随机产生三个数字,0代表父亲抢到cpu资源,1代表儿子,2代表女儿
b=rand()%2;//随机产生两个数用于确定是放桔子还是苹果,0代表桔子,1代表苹果
if(a==0){//父亲抢到cpu资源,但是前提是还没有被阻塞
if(f==0){
n++;//如果被阻塞那么后面代码不会执行,所以先n++,
//用于消除后面continue(会运行n--)的影响
continue;
}
if(b==0){//放桔子
printf("父亲抢到cpu资源\n");
putfruit(1);
}
else{//放苹果
printf("父亲抢到cpu资源\n");
putfruit(2);
}
}
else if(a==1){//儿子抢到cpu资源
if(s==0){
n++;
continue;
}
printf("儿子抢到cpu资源\n");
searchfruit(1);//找桔子吃
}
else if(a==2){//女儿抢到cpu资源
if(d==0){
n++;
continue;
}
printf("女儿抢到cpu资源\n");
searchfruit(2); //找苹果吃
}
printfruit();//打印出此时盘子里水果的情况
printf("\n");
}
return 0;
}