IPC习题
1 仓库问题
有一个仓库,可以存放 A 和 B 两种产品,仓库的存储空间足够大,但要求: (1)一次只能存入一种产品(A 或 B); (2)-N < (A 产品数量-B 产品数量) < M。 其中,N 和 M 是正整数。试用“存放 A”和“存放 B”以及 P、V 操作描述产品 A 与 产品 B 的入库过程。
分析:
A - B < M
B - A < N
所以在仓库只存放A时,A最大可取M-1。同理只存放B时,B最大为N-1。
伪代码
Semaphore mutex = 1; //互斥信号量
Semaphore a = M-1 ; //存放A的资源信号量,初值为M-1
Semaphore b = N-1; //存放B的资源信号量,初值为N-1
void StorageA:
{
while(true)
{
GetA();
P(a);
P(mutex);
PutA();
V(mutex);
V(b);
}
}
void StorageB:
{
while(true)
{
GetB();
P(b);
P(mutex);
PutB();
V(mutex);
V(a);
}
}
2.水果问题
桌子上有一只盘子,最多可容纳两个水果,每次只能放入或取出一个水果。爸爸专向盘 子放苹果(apple),妈妈专向盘子中放桔子(orange);两个儿子专等吃盘子中的桔子, 两个女儿专等吃盘子中的苹果。请用 P、V 操作来实现爸爸、妈妈、儿子、女儿之间的 同步与互斥关系。
分析:
本题需要设置4个信号量,其中empty表示还可以向盘中放几个水果,初始值为2。apple对应已放入的苹果,orange代表已放入的桔子,初始值都为0。mutex用来实现对盘子的互斥访问(放或取),初始值为1。
伪代码:
void father(){
while(true){
P(empty);
P(mutex);
向盘中放苹果();
V(mutex);
V(apple); }
}
void mother(){
while(true){
P(empty);
P(mutex);
向盘中放入桔子();
V(mutex);
V(orange);
}
void son(){
while(true){
P(orange);
P(mutex);
取出桔子();
V(mutex);
V(empty);
吃桔子();
}
}
void daughter(){
while(true){
P(apple);
P(mutex);
取出苹果();
V(mutex);
V(empty);
吃苹果();
}
}
3.理发师问题
有一个理发师,一把理发椅和 N 把供等候理发的顾客坐的椅子。如果没有顾客,则理发 师便在理发师椅子上睡觉;当一个顾客到来时,必须唤醒理发师进行理发;如果理发师正在理发时又有顾客来到,则如果有空椅子可坐,他就坐下来等,如果没有空椅子,他就离开。为理发师和顾客各编一段程序(伪代码)描述他们的行为,要求不能带有竞争条件。
分析
本题应该设置三个信号量,customers代表等待服务的顾客,初始值为0、barbers代表等待顾客的理发师,初始值为0、mutex用来实现互斥访问,初始值为1。
伪代码
#define CHAIRS 5 /* # chairs for waiting customers */
semaphore customers = 0; /* # of customers waiting for service */
semaphore barbers = 0; /* # of barbers waiting for customers */
semaphore mutex = 1; /* for mutual exclusion */
int waiting = 0; /* customers are waiting (not being cut) */
void barber(void)
{
while (true) {
P(customers); /* go to sleep if # of customers is 0 */
P(mutex); /* acquire access to 'waiting' */
waiting = waiting − 1; /* decrement count of waiting customers */
V(barbers); /* one barber is now ready to cut hair */
V(mutex); /* release 'waiting' */
cut_hair(); /* cut hair (outside critical region) */
}
}
void customer(void)
{
P(mutex); /* enter critical region */
if (waiting < CHAIRS) { /* if there are no free chairs, leave */
waiting = waiting + 1; /* increment count of waiting customers */
V(customers); /* wake up barber if necessary */
V(mutex); /* release access to 'waiting' */
P(barbers); /* go to sleep if # of free barbers is 0 */
get_haircut(); /* be seated and be serviced */
} else {
V(mutex); /* shop is full; do not wait */
}
}
4.吸烟者问题
吸烟者问题。三个吸烟者在一间房间内,还有一个香烟供应者。为了制造并抽掉香烟, 每个吸烟者需要三样东西:烟草、纸和火柴。供应者有丰富的货物提供。三个吸烟者中, 第一个有自己的烟草,第二个有自己的纸,第三个有自己的火柴。供应者将两样东西放在桌子上,允许一个吸烟者进行对健康不利的吸烟。当吸烟者完成吸烟后唤醒供应者, 供应者再放两样东西(随机地)在桌面上,然后唤醒另一个吸烟者。试为吸烟者和供应者编写程序解决问题。
伪代码
semaphore mutex = 1;
semaphore s1 = 0;
semaphore s2 = 0;
semaphore s3 = 0;
bool flag1 = true, flag2 = true; flag3 = true;
void provider(){
while(true){
P(mutex);
取两样香烟原料并用flagi标记();
if(flag2 && flag3){
V(s1);
}else if(flag1 && flag2){
V(s2);
}else{
V(s3);
}
}
}
void smoker1(){
while(true){
P(s1);
取原料做香烟();
V(mutex);
吸烟();
}
}
void smoker2(){
while(true){
P(s2);
取原料做香烟();
V(mutex);
吸烟();
}
}
void smoker3(){
while(true){
P(s3);
取原料做香烟();
V(mutex);
吸烟();
}
}