之前学了信号量机制的几个问题:
生产者消费者问题: https://www.cnblogs.com/wkfvawl/p/11529681.html
多生产者消费者问题:https://www.cnblogs.com/wkfvawl/p/11531382.html
吸烟者问题:https://www.cnblogs.com/wkfvawl/p/11534452.html
读者写者问题: https://www.cnblogs.com/wkfvawl/p/11538431.html
这里再介绍几个问题。
一、猴子过铁索问题
1、问题描述
两个山崖间有一根铁索,山崖两边各有一群猴子,任何时候同时只能有一个方向的猴子通过铁索。使用P、V操作写出山崖两边的猴子过铁索的算法。
2、问题分析
一个山上的猴子就是一群读者,第二个山上的猴子为另一群读者,两群读者互斥使用铁索。
设信号量waymutex表示山两边的猴子对铁索的互斥共享,初值为1;设m1count和m2count表示对两边猴子的记数,其初值为0;设m1mutex 和m2mutex表示两群猴子中各猴子互斥访问记数变量的信号量,初值都为1,其同步与互斥的算法如下:
semaphore waymutex=1; semaphore m1mutex=1, m2mutex=1; int m1count=0, m2count=0; Monkeygroup1() { while(1) { P(m1mutex); //第一群猴子之间互斥的访问m1count if(m1count=0)//同一方向的该群猴子中的第一个负责“加锁” { P(waymutex); } m1count=m1count+1;// V(m1mutex); 猴子通过铁索; P(m1mutex); m1count=m1count-1; if(m1count=0)//同一方向的该群猴子中的最后一个个负责“解锁” { V(waymutex); } V(m1mutex); } } Monkeygroup2() { while(1) { P(m2mutex);//第二群猴子之间互斥的访问m1count if(m2count=0) { P(waymutex); } m2count=m2count+1; V(m2mutex); 猴子通过铁索; P(m2mutex); m2count=m2count-1; if(m2count=0) { V(waymutex); } V(m2mutex); } }
3、总结
该问题是读者写者问题的变种,读者写者问题中只要求多个读者可以同时对文件读取,写者不可以。这里的铁索和文件是一样的,只有这一份临界资源,但两边的两群猴子同时只能一个方向的猴子通过,也就相当于读者写者问题中,多个写者也可以同时对文件进行操作。
该问题的另外一种描述更加贴近生活:
设A、B两点之间是一段东西向的单行车道,现在要设计一个AB路段自动管理系统,管理规则如下:当AB间有车辆在行驶时同方向的车可以同时驶入AB段,但另一方向的车必须在AB段外等待;当AB段之间无车辆行驶时,到达AB段的任一方向的车都可进入AB段,但不能从两个方向同时驶入,即只能有一个方向的车驶入;当某方向在AB段行驶的车辆驶出了AB段且暂无车辆进入AB段时,应让另一方向等待的车辆进入AB段行驶。试用信号量和P、V操作管理AB路段车辆的行驶。
二、两人下棋问题
1、问题描述
两人下象棋的过程可以概括为:一开始只能是“红先黑后”,以后两人要循环轮流走子,直至某一方获胜或双方和棋为止。这是个只有一个生产者和一个消费者的生产者——消费者问题,是个典型的“你等我,我也等你”的问题。
2、问题分析
红方是总的前趋任务——生产者进程,黑方是总的后继任务——消费者进程,但由于下棋过程必须轮流走子,所以红黑双方的生产者消费者身份会轮流改变。棋盘则是生产者与消费者共享的缓冲。
所用信号量设置如下:
Ⅰ)同步信号量hei,初值为1,表示黑方已走子,开始时可使红方先行不受阻。
Ⅱ)同步信号量hong,初值为0,表示红方尚未走子, 开始时可使黑方先行受阻。
semaphore hei = 1; semaphore hong =0; player1()//红方 { while(1) { P(hei); 若被黑方将死,则投子认负,结束; 若同意与黑方作和,则结束; 否则,根据棋局思考后走一子; V(hong); } } player2()//黑方 { while(1) { P(hong); 若被红方将死,则投子认负,结束; 若同意与红方作和,则结束; 否则,根据棋局思考后走一子; V(hei); } }
3、总结
该问题是消费者生产者问题的变种,不同于生产者消费者问题,该问题中只能有一个红方进程和一个黑方进程,二者是同步关系。
在“前操作”之后执行V(S)
在“后操作”之前执行P(S)
三、超市购物问题
1、问题描述
某小型超级市场,可容纳50人同时购物。入口处有篮子,每个购物者可拿一只篮子入内购物。出口处结帐,并归还篮子(出、入口禁止多人同时通过)。试用信号量和P、V操作写出购物者的同步算法。
2、问题分析
①所用信号量设置如下:
Ⅰ)互斥信号量S,初值为50,用以保证最多可以有50个购物者同时进入超市。
Ⅱ)互斥信号量mutex,初值为1,用以保证同时只能有一个购物者进程进入出入口拿起篮子或者结帐后放下篮子。
②用信号量机制给出的每个购物者购物过程的算法描述如下:
semaphore s = 50; semaphore mutex =1; customer() { while(1) { P(S); P(mutex); 从入口处进超市,并取一只篮子; V(mutex); 进超市内选购商品; P(mutex); 到出口结帐,并归还篮子; V(mutex); 从出口离开超市; V(S); } }
四、理发师睡觉问题
1、问题描述
理发店里有一位理发师,一把理发椅和N把供等候理发的顾客坐的椅子。
如果没有顾客,则理发师便在理发椅上睡觉。当一个顾客到来时,他必须先唤醒理发师。
如果顾客到来时理发师正在理发,则如果有空椅子,可坐下来等;否则离开。
2、问题分析
1)同步关系:只要有顾客存在,理发师就不能去睡觉,要去工作。
2)互斥关系:最多有N个顾客,理发师同一时刻只能给一位顾客理发。
2)信号灯设置:Customer:是否有顾客 mutex互斥信号灯 共享变量empty描述空椅子数
semaphore Customer = 0;//同步信号量.是否有顾客 semaphore mutex =1; int empty = N; barber() { while(1) { P(Customer); P(mutex); empty++; V(mutex); 理发; } } customer() { while(1) { P(mutex); if(empty>0)//只有还有空椅子的时候才会解锁 { empty--; V(Customer); 等待理发; } V(mutex); } }
3、总结
该问题可以看成消费者生产者问题的一个变种。将理发店的顾客看成消费者,消费的是理发店座位这种资源;将理发师看成生产者,每给一位顾客理发就会生产出一个理发店的座位。与生产者消费者问题不同的是,这里同时只能有一个生产者进程,最多有N个消费者进程,并且顾客和理发师是同步关系。