习题二参考答案
4、答:
在生产者—消费者问题中,Producer进程中P(empty)和P(mutex)互换先后次序。先执行P(mutex),假设成功,生产者进程获得对缓冲区的访问权,但如果此时缓冲池已满,没有空缓冲区可供其使用,后续的P(empty)原语没有通过,Producer阻塞在信号量empty上,而此时mutex已被改为0,没有恢复成初值1。切换到消费者进程后,Consumer进程执行P(full)成功,但其执行P(mutex)时由于Producer正在访问缓冲区,所以不成功,阻塞在信号量mutex上。生产者进程和消费者进程两者均无法继续执行,相互等待对方释放资源,会产生死锁。在生产者和消费者进程中,V操作的次序无关紧要,不会出现死锁现象。 5、答:
6、答:
设信号量sp用于控制对盘子的互斥操作,信号量sg1用于计数,表示盘子中的苹果数目,信号量sg2用于计数,表示盘子中的桔子数目。
Semaphore sp=1,sg1=0,sg2=0
dad() {
while(1)
{ prepare an apple; p(sp);
put an apple on the plate; v(sg2);} } mom() {
while(1)
{prepare an orange; p(sp);
put an orange on the plate; v(sg1);} } son() {
while(1) {
p(sg1);
take an orange from the plate; v(sg);
eat the orange; } }
daughter() {
while(1) {
p(sg2);
take an apple from the plate; v(sg);
eat the apple; } }
7、答:为了使写者优先,在原来的读优先算法基础上增加一个初值为1的信号量S,使得当至少有一个写者准备访问共享对象时,它可使后续的读者进程等待写完成;初值为0的整型变量writecount,用来对写者进行计数;初值为1的互斥信号量wmutex,用来实现多个写者对writecount的互斥访问。 reader(){
while(1){ P(s); P(rmutex);
if(readcount= =0)P(mutex); readcount++; V(rmutex); V(S); 读文件; P(rmutex); readcount --;
if (readcount==0)V(mutex); V(rmutex); } }
writer()[
while(1){
P(wmutex);
if(writecount= =0)P(S); writecount++; V(wmutex); P(mutex); 写文件; V(mutex); P(wmutex); writecount- -;
If (writecount= =0)V(S); V (wmutex); }
9、答:
信号量sofa:表示等候椅数,初值为n 信号量empty:表示理发椅空,初值为1 信号量full:表示理发椅上有顾客,初值为0 count:记录等候椅上的人数,初值为0
信号量mutux:用来实现对变量count的互斥访问Var mutex,sofa,empty,full: semaphore=1,n,1,0; count: integer: =0;
Guest: begin repeat P(mutex); if (count>=n) then begin V(mutex); 离开; end
else
Barber: begin repeat P(full) 剪发; V(empty); until false end begin
count:=count+1;
if (count>1) then //多个顾客时,坐等候椅上 V(mutex);
P(sofa); 坐沙发等; P(empty); 坐椅子上; V(sofa);V(full);
else //只有一个顾客时,坐到理发椅上 begin
V(mutex);
P(empty); 坐椅子上; V(full); end 剪发 离开; P(mutex);
count:=count-1; V(mutex); end until false end
11、答:
本题中中共有三类进程,相当于机房管理员进程guard,学生进程student和教师进程teacher。 相应的信号量和各个进程描述如下: semaphore computer=2m; /*对应于计算机的资源信号量*/ semaphore student=0;
/*对应于欲进入机房的学生*/ semaphore enter=0;
/*用来控制学生是否可进入机房*/
semaphore finish=test=0; /*用来同步学生和教师——教师须检查实习完毕的学生*/ student_i(){ /*i=1,2,···2n*/ V(student);
/*激活管理员,有学生到达,要进入机房实验*/ P(enter); /*等待管理员激活进入机房*/ 进入机房上机实习;
V(finish); /*激活教师已经做完实验*/ P(test); /*等待教师检查作业*/ 离开机房;
V(computer); /*所占用的计算机变为空闲*/ } guard(){
int i;
for(i=0;i++;i P(computer); /*等待有两个空闲计算机*/ P(computer); P(student); /*等待有两个学生达到*/ P(student); V(enter); /*激活两个等待进入机房的学生*/ V(enter); }} teacher(){ int i; for(i=0;i++;i P(finish); /*等待两个学生完成实验*/ P(finishi); 检查两个学生的实习结果; V(test); /*检查完后,激活两个学生检查完毕,可以离开机房*/ V(test); }} 附加1:图书馆阅览室问题 问题描述:假定阅览室最多可同时容纳100个人阅读,读者进入时,必须在阅览室门口的一个登记表上登记,内容包括姓名、座号等,离开时要撤掉登记内容。用P、V操作描述读者进程的同步算法。 mutex,emptyseat semaphore; 阅读; mutex=1,Emptyseat=100; P(mutex); Cobegin { 查登记表,置空; Reader(i){ V(mutex); P(Emptyseat); 离开; P(mutex); V(Emptyseat); 查登记表,登记姓名,座位号等; }} V(mutex); Coend 附加2:哲学家就餐问题 给所有哲学家编号,奇数号的哲学家必须先拿左边的筷子,偶数号的哲学家必须先拿右边的筷子。这样,任何一个哲学家拿到一支筷子后,就已经阻止了他邻座的一个哲学家吃饭的企图,除非某个哲学家一直吃下去,否则不会有人会饿死。 Repeat else begin begin if (i mod 2)!=0 then P(chopstick[(i+1) mod 5]); begin P(chopstick[i]); P(chopstick[i]); …eat;… P(chopstick[(i+1) mod 5]); V(chopstick[(i+1) mod 5]); …eat;… V(chopstick[i]); V(chopstick[i]); … think; … V(chopstick[(i+1) mod 5]); end … think; … end end until false;