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的关系:
- 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)
- 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);
}