操作系统习题3—进程的互斥与同步
1.例举两个现实生活中需要同步与互斥的例子。
我们去吃自助餐时,店里的厨师会在后台厨房制作食物,然后将食物运送到公共饮食区域,让顾客自行挑选。如果公共饮食区域的食物都被顾客吃光了,那么顾客只有先进行等待,等厨师做出更多食物再送到公共饮食区;如果公共饮食区域食物数量多到一定程度,厨师会暂停制作食物。
驾驶员开车行驶到一个十字路口时,如果本路口的绿灯亮起,驾驶员可以顺利通过;如果本路口的红灯亮起,驾驶员必须停车进行等待,让其他路口的车辆通过。
2.何谓原语?它与系统调用有何区别?如何实现原语执行的不可分割性?
原语是由若干条机器指令构成的可完成特定功能的程序段。具有以下三个特点:
- 处于操作系统最底层,是最接近硬件的部分
- 程序的运行具有原子性,作为一个整体而不可分割,即要么全都完成,要么全都不做
- 程序的运行时间都较短,而且调用频繁
原语与系统调用的区别:原语只要强调操作的不可分割性,可以认为是一个不可中断的子程序调用;系统调用是由用户态进入核心态,一般也不会被中断,但如果有更紧迫的系统调用的话,原来的系统调用还是会被打断。
原语可通过硬件实现不可中断性,或通过实现临界段的元方法(屏蔽中断、加硬锁)达到不被逻辑上中断。
3.如果 P、V 操作不作为原语,即可分割执行,那么是否还可以用于
解决互斥问题?若不能,举例说明。
如果 P、V 操作不作为原语,就不能用于解决互斥问题。
举例:在生产者-消费者问题中,由于 P、V 操作可以分割执行,很大可能会出现当前缓冲池中满缓冲区个数仅为 1,而多个消费者同时成功使用到这个缓冲区的情况,造成不可避免的系统错误。
4.请用并行语句和 P、V 操作描述图 1 所示的任务执行过程
int synch=0; //两进程 P1、P2 共享信号量
Parbegin
P1():{
S1;
V(synch);
S2;
S4;
V(synch);
S5;
V(synch);
}
P2():{
P(synch);
S3;
P(synch);
S6;
P(synch);
S7;
}
Parend;
5.“理发师睡觉”问题:假设理发店由等待间(n 个座位)和理发间(只有一个座位)构成。无顾客时,理发师睡觉。顾客先进等待间再进理发间,当顾客进入理发间发现理发师在睡觉时,则唤醒理发师,请求理发;如果理发师正在理发,又有顾客到来时,只要有空椅子,他就坐下来等待,如果没有空椅子,他就离开。请为理发师和顾客各编写一段程序来描述他们的同步问题。
int customer=0,barber=0; //顾客和理发师的信号量
int customerNumber=0,mutex=1; //当前顾客数目和互斥控制量
//理发师
Barber(){
while(1){
P(customer); //唤醒等待的一位顾客
P(mutex); //顾客被唤醒,准备理发。没有顾客就睡觉
customerNumber--; //店里顾客数减一
V(barber); //有顾客来了,醒来理发
V(mutex); //释放信号量
}
}
//顾客
Customer(){
while(1){
P(mutex); //顾客想要理发
if(customerNumber<N){ //理发店人数未满,进店
customerNumber++; //店里顾客数加一
V(customer); //唤醒理发师理发
V(mutex); //释放信号量
P(barber); //理发师进行理发
}
else //理发店人数已满,离店
V(mutex);
}
}