2.16吸烟者问题

一,问题描述:

假设系统有三个抽烟者进程和一个供应者进程。每个抽烟者不停的卷烟并抽掉它,但是要卷起并抽点一支烟,抽烟者需要三种材料:烟草,纸和胶水。三个抽烟者中,第一个有烟草,第二个有纸,第三个有胶水。供应者进程无限地提供三种材料,供应者每次将两种材料放到桌子上,拥有剩下那种材料的吸烟者就会卷一支烟抽掉它,并给供应者一个信号,告诉它我抽完了,供应者就会放另外两种材料到桌子上,这个过程一直重复(让三个抽烟者轮流抽烟)

二,问题分析

1,关系分析:找出题目描述各个进程,分析他们之间的同步关系

1)互斥关系:对缓冲区(桌子)的访问需要互斥进行,但由于缓冲区大小为1,只有一个生产者,只是它提供多种产品,所以可以不设置互斥信号量,它本身也可以互斥进行。

2)同步关系:

桌子上有纸和胶水——》第一个吸烟者可以吸烟——设置同步信号量offer1

桌子上有烟草和胶水——》第二个吸烟者可以吸烟——设置同步信号量offer2

桌子上有纸和烟草——》第三个吸烟者可以吸烟——设置同步信号量offer3

吸烟者完成吸烟——》供应者可以放材料到桌子上——设置同步信号量finish

2,整理思路:根据各个进程的操作流程确定P,V操作的大致顺序

扫描二维码关注公众号,回复: 11373162 查看本文章

互斥:需要在临界区前后分别执行P操作,和V操作。

同步:前一个进程执行后执行V操作,后一个进程进入临界区之前执行P操作

三,具体实现:

semaphore offer1=0;  //桌子上组合一的数量
semaphore offer2=0;  //桌子上组合二的数量
semaphore offer3=0;  //桌子上组合三的数量
semaphore finish=0;  //抽烟是否完成
int i=0;            //用于实现三个抽烟者轮流抽烟

provider(){
    while(1){
        if(i==0){
            将组合一放到桌上;
            V(offer1);//唤醒第一个抽烟者
        }
         else if(i==1){
            将组合一放到桌上;
            V(offer1);//唤醒第一个抽烟者
        }
         else if(i==2){
            将组合一放到桌上;
            V(offer1);//唤醒第一个抽烟者
        }
        i=(1+1)%3;
        P(finish);因为刚开始,桌子是空的,所以在这里执行P操作,如果桌上的材料没被取走就自动进入堵塞态,直到吸烟者吸烟完成并执行了V(finish)开始下一轮的放材料
    }
}

smoker1(){
    while(1){
        P(offer1);
        从桌上拿走组合一,卷烟,抽掉;
        V(finish);//唤醒供应者进程供应材料
    }
}

smoker2(){
    while(1){
        P(offer2);
        从桌上拿走组合二,卷烟,抽掉;
        V(finish);//唤醒供应者进程供应材料
    }
}

smoker3(){
    while(1){
        P(offer3);
        从桌上拿走组合三,卷烟,抽掉;
        V(finish);//唤醒供应者进程供应材料
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_44841312/article/details/105310162