看完我的前三篇关于进程同步的经典题型后,下面开始一些真题练习吧!
1.在仓库里进行存放、拿取零件问题
问题描述:
某工厂有两个生产车间和一个装配车间,两个生产车间分别生产A,B两种零件,装配
车间的任务是把A,B两种零件组装成产品。两个生产车间每生产一个零件后,都要分别把它们送到专配车间的货架F, F2上。F1存放零件A,F2存放零件B,F1和 F2的容量均可存放10个零件。装配工人每次从货架上取一个零件A和一个零件B后组装成产品。请用 P,V操作进行正确管理。
问题分析:
两个生产车间和一个装配车间,所以一共有三个进程,因为说可以存放10个或者(n)个零件,给予了具体的数,用到empty和full两个信号量。货架F1,F2每次只能取一个所以需要互斥信号量mutex1,mutex2。但在装配车间过程中,也是向F1,F2仓库里拿零件,因此不需要再写一个互斥信号量,在进入F1,F2仓库时只需要仓库自己的mutex1,mutex2即可。
伪代码:
//定义信号量
semaphore mutex_1=mutex_2=1;
semaphore empty_1=empty_2=10;
semaphore full_1=full_2=0;
//A车间的工作过程可描述为:
product_A(){
while(1){
生产一个产品 A;
P(empty_l); //判断货架F1是否有空
P(mutex_l); //互斥访问货架F1
将产品A存放到货架F1上;
V(mutex_l); //释放货架F1
V(full_l); //货架F1上的零件A的个数加1
}
}
//B车间的工作过程可描述为:
product_B(){
while(1){
生产一个产品 B;
P(empty_2); //判断货架F2是否有空
P(mutex_2); //互斥访问货架F2
将产品B存放到货架F2上;
V(mutex_2); //释放货架F2
V(full_2); //货架F2上的零件B的个数加1
}
}
//装配车间的工作过程可描述为:
assemble(){
while(1){
P(full_1); //判断货架F1上是否有产品A
P(mutex_1); //互斥访问货架F1
从货架F1上取一个A产品;
V(mutex_l); //释放货架F1
V(empty_l); //货架F1上的空闲空间数加
P(ful1_2); //判断货架F2上是否有品
P(mutex_2); //互斥访问货架F2
从货架F2上取一个B产品;
V(mutex_2); //释放货架F2
V(empty_2); //货架F2上的空闲空间数加1
将取得的A产品和B产品组装成产品;
}
}
2.老和尚、小和尚取水问题
问题描述:
某寺庙有小和尚、老和尚若干,有一水缸,由小和尚提水入缸供老和尚饮用。水缸可容
10桶水,水取自同一井中。水井径窄,每次只能容一个桶取水。水桶总数为3个。每次入缸取水仅为1桶水,且不可同时进行。试给出有关从缸取水、入水的算法描述。
问题分析:
根据题意,了解到一共需要用到水缸(vat)、井(well)、桶(pail)三个信息量,两个进程分别是小和尚打水(前提发现缸里水不满10桶,提桶往井里打水)和老和尚喝水(前提:缸里有水可以拿桶从缸里提水喝)。
因此首先代码定义:
Vat=1;//老和尚们互斥访问缸,相当于我们之前用的mutex。(照应题中的“每次入缸取水仅为1桶水”)
Well=1;//小和尚们互斥访问水井(照应题中的“水井径窄,每次只能容许一个桶取水”)
Pail=3;//表明水桶数量(照应题中的水桶总数为3)
那么临界空间资源是什么呢,通过题目可以发现,不管是老和尚还是小和尚都会用到水缸,而且桶里的水最终也会倒在缸里,因此临界资源是缸,其实还有一个地方可以确认缸是临界资源,题目中给出了水缸可容纳10桶水(一般给出空间容纳量的就是我们的临界资源)。确认了临界资源后,要确认缸里的水有多少,满不满。那就要用到empty和full两个信号量进行确认。
伪代码:
//定义信号量
semaphore well=1; //用于互斥地访问水井
semaphore vat=1; //用于互斥地访问水缸
semaphore empty=10; //用于表示水缸中剩余空间能容纳的水的桶数
semaphore full=0; //表示水缸中的水的桶数
semaphore pail=3; //表示有多少个水桶可以用,初值为3
//小和尚
while(1){
P(empty); //先判断水缸是否可以再添水
P(pail); //可以添水则拿起桶,互斥访问桶
P(well); //互斥访问井
从井中打一桶水;
V(well); //打完水释放井
P(vat); //将水倒进缸中,互斥访问缸
将水倒入水缸中;
V(vat); //倒完睡,离开缸
V(full); //此时缸中水加一桶
V(pail); //释放桶
}
//老和尚
while(l){
P(full); //先判断缸中是否有水可以饮用
P(pail); //拿桶,互斥访问桶
P(vat); //使用水桶往缸中取水
从水缸中打一桶水;
V(vat); //打完水后,释放对缸互斥
v(empty); //此时缸中的水减少一桶的量
喝水;
V(pail); //喝完水后释放桶
}
3.博物馆参观问题
问题描述:
某博物馆最多可容纳500人同时参观,有一个出入口,该出入口一次
仅允许一人通过。参观者的活动描述如下: cobegin
参观者进程i:{
...
进门。
参观;...
出门;
coend
请添加必要的信号量和P,V[或 wait(),signal()]操作,以实现上述过程中的互斥与同步。要求写出完整的过程,说明信号量的含义并赋初值。
问题分析:
出入口一次仅允许一个人通过,设置互斥信号量mutex,初值为1。博物馆最多可同时容纳500人,因此设置信号量empty,初值为500。
将门看作是临界资源,那么进入和离开的时候都需要访问这个临界资源,因此需要两对P、VCC操作。
伪代码:
//定义信号量
Semaphore empty=500; //博物馆可以容纳的最多人数
Semaphore mutex=l; //用于出入口资源的控制
cobegin
参观者进程i:
{
***
P(empty); //判断是否还可以进人
P(mutex); //可以则进入,互斥使用门
进门;
V(mutex);//进入以后则释放对门的访问
参观;
P(mutex); //参观完离开,互斥使用门
出门;
V(mutex);//离开博物馆,释放对门的访问
V(empty);' //可容纳人数增1
...
}
coend
希望这篇练习能够使你对进程同步问题有更深的了解和认识。