1.理解生产者和消费者问题
没有引入信号量时的生产者和消费者进程,什么情况下会出现结果不唯一?什么情况下会出现永远等待?
答:当生产者生产完商品之后,在商品进入等待队列之前发生中断,会出现结果不唯一的情况;
当最后一个商品进入等待队列之后,在唤醒消费者之前发生中断,会出现等待队列已满,生产者在等待消费者消费,消费者则等待生产者唤醒,即出现永远等待的情况。
用信号解决生产者和消费者的同步与互斥,要求能自己写出来。
int empty = 1; int full = 0; int mutex = 1; process product(){ whiile(true){ process(); P(empty); P(mutex); 商品数加一 V(mutex); V(full); } } process consume(){ while(true){ P(full); P(mutex); 商品减一 V(mutex); V(empty); consume(); } }
2.哲学家吃面问题
semaphore fork[5]; for(int i;i<=5;i++){ fork[i]; } process philosopher(){ while(true){ think(); P(fork[i]); P(fork[(i+1)%5]; eat(); V(fork[i]); V(fork[(i+1)%5); } }
3.读写文件问题
int readcount = 0; //读进程计数 semaphore writeblock = 1; //写信号量 semaphore mutex = 1; //互斥信号量 process read(){ P(mutex); readcount++; if(readcount==1){ P(writeblock); V(mutex); 读文件; P(mutex) readcount--; if(readcount==0){ V(writeblock); } V(mutex); } } process write(){ P(writeblock); 写文件; V(writeblock); }
4.理发师问题
int writing = 0; int chair = n; semaphore customer = barbers = 0; semaphore mutex=1; process barber(){ while(true){ P(customers); //判断是否有顾客,若无顾客。理发师睡眠 P(mutex); //若有顾客,进入临界区 writing--; //等待人数减一 V(barber); //理发师准备为顾客理发 V(mutex); //退出临界区 cuthair(); //理发师正在理发(非临界区) } } process customer(){ P(mutex); //进入临界区 If(waiting < chair){ //判断是否有空椅子 writing++; //若有空椅子,等待人数加一 V(customer); //唤醒理发师 V(mutex); //退出临界区 P(barber); //理发师忙,顾客坐着等待 get_haircut(); //否则,顾客可以理发 }else V(mutex); //人满了,顾客离开 }
5.在一间酒吧里有三个音乐爱好者队列,第一队的音乐爱好者只有随身听,第二队只有音乐磁带,第三队只有电池。而要听音乐就必须随身听、音乐磁带和电池这三种物品俱全。酒吧老板一次出售这三种物品中的任意两种。当一名音乐爱好者得到这三种物品并听完一首乐曲后,酒吧老板才能再一次出售这三种物品中的任意两种。于是第二名音乐爱好者得到这三种物品,并开始听乐曲。全部买卖就这样进行下去。试用P,V操作正确解决这一买卖。
semaphore S1=S2=S3=music_over = 0; parbegin{ fan1:begin{ wait(S1); 买音乐磁带和电池; 听乐曲; signal(music_over); }end fan2:begin{ wait(S2); 买随身听和电池; 听乐曲; signal(music_over); }end fan3:begin{ wait(S2); 买随身听和音乐磁带; 听乐曲; signal(music_over); }end boss:begin{ repeat 提供任意两种物品出售; if(提供的是音乐磁带和电池) signal(S1); else if(提供的是随身听和电池) signal(S1); else signal(S1); until false; }end }parend
6.某银行有人民币储蓄业务,由n个储蓄员负责。每个顾客进入银行后先取一个号,并且等着叫号。当一个储蓄人员空闲下来,就叫下一个号。请用P,V操作正确编写储蓄人员和顾客进程的程序。
Semaphore mutex = 1,full = 无穷; Cobegin{ customer(){
While(1){
Wait(mutex);
取号;
Signal(mutex);
等待;
Signal(full);
}
}
bank(){
While(1){
Wait(full);
Wait(mutex);
叫号;
Signal(mutex);
服务;
}
}
}Coend;
7.下面是两个并发执行的进程。它们能正确运行吗?若不能请举例说明,并改正之。(5分)
parbegin
var X:integer;
process P1 process P2
var y,z:integer: var t,u:integer;
begin begin
x:=1; x:=0:
y:=0: t=0;
if x≥l then y:=y十1; if x≤l then t:=t+2;
z:=y; u:=t;
end; end;
parend.
答:进程不能正确执行。当进程执行答进程1中的"x:=1"出现中断请求执行进程2,执行进程2时把x的值改为了0,进程2执行完毕后返回继续执行进程1时,x的值已经由原来的1变为了0,将导致进程执行的结果出现错误。导致进程结果不正确的是因为进程1和2没有实现互斥,在x的值改变之前就要给利用互斥信号量给相应的进程上锁,直到进程执行到与x的值变化无关时才能为进程解锁。具体修改如下:
parbegin
var X:integer;
semaphore mutex;
mutex = 1;
process P1 process P2
var y,z:integer: var t,u:integer;
begin begin
P(mutex); P(mutex);
x:=1; x:=0:
y:=0: t=0;
if x≥l then y:=y十1; if x≤l then t:=t+2;
V(mutex); V(mutex);
z:=y; u:=t;
end; end;
parend.
8.在一个盒子里,混装了相等数量的黑棋子和白棋子,现要用自动分拣系统把黑棋子和白棋子分开,该系统由两个并发执行的进程P1和P2组成,其中进程P1专门拣黑子,进程P2专门拣白子。规定两个进程轮流拣子且每个进程每次只拣一个子。当一个进程在拣子时不允许另一个进程去拣子,并设P1先拣。请用P,V操作管理这两个并发进程,使其能正确实现上述功能。
semaphore S1,S2; //信号量S1、S2分别表示白子、黑子 S1 = 1,S2 = 0; cobegin{ process P1 begin{ repeat P(S1); 拣白子 V(S2); until false; }end process P2 begin{ repeat P(S2); 拣黑子 V(S1); until false; }end }coend