王道第二章信号量习题

Page96
3.

解题思路:
互斥资源:缓冲区智能互斥访问,因此设置互斥信号量buffer
同步问题:P1,P2因为奇数的放置和取用而同步,设置同步信号量odd;
P1,P3因为偶数的放置和取用同步,设置同步信号量even;
P1,P2,P3共享缓冲区,设置同步信号量empty,初值为N
这里互斥信号量buffer和empty不能合并为一个,因为这里的缓冲区大小>1, 无法同时保证互斥和同步,若缓冲区的大小为1,则可以合并为一个信号量即可;
buffer和empty不能合并的原因:假设,buffer=N,则P1执行P(buffer)后,buffer≠0,则P2也可以执行P(buffer),即P1,P2可以同时进入缓冲区,没有保证缓冲区的互斥使用

semaphore buffer = 1;//缓冲区的互斥
semaphore empty = N;//缓冲区的空位
semaphore odd = 0;//奇数的个数
semaphore even = 0;//偶数的个数
cobegin{
   P1{
       while(true){
           int i = produce();//生产产品
           P(empty);//查看是否有空位置
           P(buffer);//获取缓冲区的使用权
           put(i);
           V(buffer);
           if(i%2==0)
               V(even);
           else
               V(odd);
       }
   }
   P2{
       while(true){
           P(odd);//如果有奇数,则还要获取缓冲区的权限
           P(buffer);
           getodd();
           V(buffer);//释放缓冲区的权限
           V(empty);//并产生一个空位
           countodd();//统计奇数的个数
       } 
   }
   P3{
       while(true){
           P(even);
           P(buffer);
           geteven();
           V(buffer);
           V(empty);
           counteven();
       }
   }
}	

6.

仓库的为临界资源,要保证互斥。
A,B的关系:

  1. A-B<M, 即可以假设B=0;则A最大为M-1;所以每放入一个A就会有P(Sa); 当放入M-1个A后,Sa=0, 再执行P(Sa)时就会被阻塞;而对于B(B-A<N)来说,每放入一个A,则说明A的数量在变大,则在满足B-A<N的情况下,B可放入的上限也在变大,所以这时要V(Sb)
  2. B-A<N;分析同上
6.
semaphore s=1;//仓库使用权
semaphore a=M-1;
semaphore b=N-1;
A{
    P(a);
    P(s);//获取仓库的使用权
    A放入仓库;
    V(s);
    V(b);
}
B{
    P(b);
    P(s);
    B放入仓库;
    V(s);
    V(a);
}

7.

7.
Semaphore mutexi=1,mutexj=1;//互斥信号量,用于对i,j的访问和修改
Costumer{
    进入面包店;
    P(mutexi);//互斥访问i
    取号i;
    i++;
    V(mutexi);//释放对i的访问
    等待叫号i并购买面包;
}
SalesMan{
    while(true){
     	P(mutexj);
        if(j<=i){
            叫号j;
            j++;
            V(mutexj);
            销售面包;
        }
        else{
            V(mutexj);//@@@
            休息ing;
        }
    }
}

8.

直接用信号量来表示人是否满了,而不是用变量count,用count也可以,但是count还需要信号量来保证互斥,且比较麻烦;注意思维的转换!!!

8.
//count=0;semaphore mutex_count=1;//对count互斥访问
semaphore count=500;
semaphore door=1;//门的访问权
cobegin
  	参观者进程i: {
        ...
        P(count);//先看人是否满了
        P(door);//再申请获取门的权限
        进门;
        V(door);//进门后释放门的权限
        ...
        参观;
        ...
        P(door);
        出门;
        V(door);
        V(count);//出门后人数+1
        ...
    }
coend

9.

9.
semaphore empty1=10;
semaphore full1=0;
semaphore empty2=10;
semaphore full2=0;
semaphore mutex1=1;//货架F1的互斥使用
semaphore mutex2=1;//货架F2的互斥使用
P1{//1号车间生产A
   	while(true){
        生产一个A零件;
        P(empty1);//有空位
        P(mutex1);//获取使用权
        放入一个A零件;
        V(mutex1);
        V(full1);
    }
}
P2{//2号车间生产B
    while(true){
        生产一个B零件;
        P(empty2);
        P(mutex2);
        放入B零件;
        V(mutex2);
        V(full2);
    }
}
Worker{
    while(true){
        P(full1);
        P(mutex1);
        取走一个A零件;
        V(mutex1);
        V(empty1);

        P(full2);
        P(mutex2);
        取走一个B零件;
        V(mutex2);
        V(empty2);

        组装成产品;
    }
}

10.

注意:小和尚,老和尚,都是先判断缸中有无水,再去拿水桶,而不是先拿水桶!!!

10.
semaphore jing=1;//井的使用权
semaphore tong=3;//桶的个数
sempahore gang=1;//缸的使用权
semaphore empty = 10;//缸的容量:10桶水
semaphore full=0;
小和尚{
    while(true){
        //P(tong);//拿到一个桶
        P(empty);//这里应该先看是否有空位,而不是先拿桶
        P(tong);
        走到井边;
        P(jing);//获取井的使用权
        打水;
        V(jing);
        走到缸边;
        P(gang);//获取缸的使用权
        倒水入缸;
        V(gang);
        V(full);//提醒老和尚有水了
        V(tong);//放下桶,休息休息
    }
}
老和尚{
    while(true){
        口渴了;
       // P(tong);//拿起一只桶;走到缸边;
        P(full);//缸中有水
        P(tong);//这里应该先看有无水,而不是先拿起桶
        P(gang);//获取缸的使用权
        用桶取水;
        V(gang);
        V(empty);//提醒小和尚有空位了
        喝水;
        V(tong);//喝饱了,放下桶
    }
}

11.

我的解法,感觉更简洁?

semaphore a=0;
semaphore b=0;
semaphore y=0;
semaphore z=0;
P1{
    通过输入设备读入a;
    V(a);//a被读入
    P(b);//等b读入进程,来计算x
    x=a+b;
    P(z);//等z计算出来,z一旦计算出来,说明y一定计算出来了
    打印x,y,z;
}
P2{
    P(a);//a被读入后才能轮到p2读
    通过输入设备读入b;
    V(b);//b被读入,唤醒p1,p3
    V(b);
    y=a*b;
    V(y);//y计算出来了
}
P3{
    P(b);//b被读入后才能轮到p3读
    通过输入设备读入c;
    //V(c);//c被读入
    P(y);//等y计算出来
    z=y+c-a; 
    V(z);
}

答案解法:

semaphore s1=1;
semaphore s2=0;
semaphore s3=0;

semaphore sb=0;
semaphore sy=0;
semaphore sz=0;

P1(){
    P(s1);//
    从输入设备输入数据a;
    V(s2);
    P(sb);//等待b输入,这样才能计算x
    x=a+b;
    P(sy);//等待y计算好
    P(sz);//等待z计算好
    打印出x,y,x;
}
P2(){
    P(s2);//等待a输入到p1
    从输入设备输入数据b;
    V(s3);
    V(sb);
    y=a*b;
    V(sy);//y计算出来了,提醒p1,p3
    V(sy);//
}
P3(){
    P(s3);//等待b输入到p2
    从输入设备输入数据c;
    P(sy);//等待y计算好
    z=y+c-a;
    V(sz);//z计算好了
}

12.

按理说,营业员的V(empty)和V(service),谁前谁后均可
service不能初始化为1,因为你不知道营业员啥时候准备好工作,所以还是由营业员来V(service)比较好

semaphore machine=1;//取号机互斥使用
semaphoore empty=10;//空座位
semaphore full=0;//等待的顾客人数
semaphore service=0;//服务窗口
cobegin{
    process 顾客i
    {
        P(empty);//有空位才取号
        P(machine);//获取取号机的使用权
        从取号机获取一个号码;
        V(machine);
        V(full);//占一个座位
        P(service);//等待被叫号
        获取服务;
	}
    
    process 营业员
    {
        while(true){
            P(full);//先看有没有人来
            V(empty);//空出来一个位子
            V(service);//叫号
            为客户服务; 
        }
    }
}


13

(1)
semaphore bridge=1;//桥的使用权

NorthToSouth{
    P(bridge);
    过桥;
    V(bridge);
}
SouthToNorth{
    P(bridge);
    过桥;
    V(bridge);
}

(2) 读写者中,连读的变形

(2)
NtoS = 0;//同方向的车辆个数
semaphore bridge=1;
semaphore s1=1;//互斥访问并修改NtoS;
StoN = 0;
semaphore s2=1;

NToS{
    P(s1);
    if(NtoS == 0){//说明这是第一个,则需要获取bridge
        P(bridge);
    }
    NtoS++;
    V(s1);//同方向的车辆数加1
    过桥;
    P(s1);
    if(NtoS == 1){//说明这是最后一个过桥的,要释放bridge
        V(bridge);
    }
    NtoS--;
    V(s1); 
}
SToN{
    P(s2);
    if(StoN == 0){
        P(bridge);
    }
    StoN++;
    V(s2);
    过桥;
    P(s2);
    if(StoN == 1){
        V(bridge);
    }
    StoN--;
    V(s2);
}

15

注意考虑死锁问题,不能让箱子中全部装成车轮或全部装车架,这样就会死锁。还有自行车有两个轮子!!!
为什么答案不用加入互斥量mutex
这里的三个工人可以同时往缓冲区中存入/取出东西???

semaphore empty=3;//箱子的空位
semaphore chejia=0;//箱子中的车架
semaphore chelun=0;//车轮
semaphore s1=N-2;//车架的最大数目
semaphore s2=N-1;//车轮的最大数目
semaphore mutex=1;//箱子的使用权

Worker1{
    do{
       	加工一个车架;
        P(s1);//检查车架是否达到最大数目
        P(empty);//有空位才能放
        P(mutex);//获取架子的使用权
        车架放入箱中;
        V(mutex);//释放架子的使用权
        V(chejia);//说明有车架了,可以取了
    }while(1)
}
Worker2{
    do{
        加工一个车轮;
        P(s2);//检查车轮是否到达最大数目
        P(empty);
        P(mutex);
        车轮放入箱中;
        V(mutex);
        V(chelun);  
    }while(1)
}
Worker3{
    do{ 
        P(chejia);//箱子中有车架才能去取
        P(mutex);
        取出一个车架;
        V(mutex);
        V(empty);
        V(s1);//可装入车架数目+1

        P(chelun);
        P(chelun);
        P(mutex);
        取出两个个车轮;
        V(mutex);
        V(empty);
        V(empty);
        V(s2)
        V(s2);//可装入车轮数目+2
        
        组装成一台车;
    }while(1)
}

16

semaphore mutex=1;
semaphore full=0;
semaphore empty=1;

P{
    while(1){
        生成产品;
        P(empty);
        P(mutex);
        放入产品;
        V(mutex);
        V(full);
    }
}
Q{
    while(1){
        P(full);
        P(mutex);
        取出产品;
        V(mutex);
        V(empty);
        消费产品;
    }
}
R{
    while(1){
        if(empty == 1){//执行生产者功能
            生产产品;
            P(empty);
            P(mutex);
            放入产品;
           	V(mutex);
            V(full);
        }
        
        //这里应该是可以用else的,因为这里缓冲区只有1个大小,要么空要么满
        if(full == 1){
            P(full);
            P(mutex);
            取出产品;
            V(mutex);
            V(empty);
            消费产品;
        }
    }
}

17

我的答案,感觉不太对

semaphore empty=10;//10个空椅子
semaphore full=0;//等待理发的人
semaphore servic=0;
理发师{
    while(1){
        P(full);
        V(empty);//则空出来一个位子
        V(service);
        给客人理发;
    }
}
顾客{
    while(1){
        P(empty);//先看有无空位
        V(full);//等待理发的人+1
        P(service);//等待理发服务
        理发; 
    }
}
int waiting=0;//等候理发的顾客数
int chairs=10;//为顾客准备的椅子数

semaphore customers=0;
semaphore barbers=1;
semaphore mutex=1;

barber{
    while(1){
        P(customers);//若无顾客则理发师睡觉
        P(mutex);
        waiting=waiting-1;
        V(barbers);//理发师为一个顾客去理发
        V(mutex);
        理发;
    }
}

customer{
    P(mutex);
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值