1.阅览室登记
问题
有一阅览室,共有100个座位。读者进入时必须先在一种登记表上登记,该表为每一座位列一个表目,包括座号和读者姓名。读者离开时要注销掉登记内容。试用P、V原语描述读者进程的同步问题。
关系分析
- 同步关系:座位的使用
- 互斥关系:登记、注销互斥操作
代码
semaphore empty = 100; // 记录空座位数量 semaphore mutex = 1; // 互斥信号量,互斥访问登记和注销操作 void reader() { while(true) { P(empty); P(mutex); // 登记 V(mutex); // read P(mutex); // 注销 V(mutex); V(empty); } }
2.动物存放
问题
有一只铁笼子,每次只能放入一只动物,猎手向笼子里放入老虎,农民向笼子里放入猪;动物园等待取笼子里的老虎,饭店等待取笼子里的猪。现请用P、V操作写出能同步执行的程序。
关系分析
- 同步关系
- 放 --> 取
代码
信号量
semaphore box = 1; // 记录笼子是否为空 semaphore tiger = 0; // 老虎的同步信号量 semaphore pig = 0; // 猪的同步信号量
猎人
void hunter() { while(true) { P(box); // 放入老虎 V(tiger); } }
农民
void famer() { while(true) { P(box); // 放入猪 V(pig); } }
动物园
void zoo() { while(true) { P(tiger); // 取走老虎 V(box); } }
饭店
void restaurant() { while(true) { P(pig); // 取走猪 V(box); } }
3.售票
问题
某车站售票厅,任何时刻最多可容纳20名购票者进入,当售票厅中少于20名购票者时则厅外的购票者可立即进入,否则需在外面等待。若把一个购票者看作一个进程,请回答下列问题
(1) 用PV操作管理这些并发进程时,应怎样定义信号量?写出信号量的初值以及信号量各种取值的含义。
(2) 若欲购票者最多为n个人,写出信号量可能的变化范围(最大值和最小值)。
答案
(1)定义一信号量S,初始值为20。
- S>0,S的值表示可继续进入售票厅的人数;
- S=0,表示售票厅中已有20名顾客(购票者);
- S<0,|S|的值为等待进入售票厅的人数。(2)由于s的值表示的是在售票厅有多少个座位,因此最大值为s(表示没有人)最小值为s-n(根据n来决定)
4.司机售票员
问题
在公共汽车上,司机负责开车、停车和驾驶,售票员负责门的开门、关门和售票。基本操作规则是只有停车后,售票员才能开门;只有售票员关门后,司机才能开车。汽车初始状态处于行驶之中。当只有1个司机、2个售票员、2个门、每个售票员负责一个门时的协调操作。请使用P、V原语实现售票员与司机之间的协调操作说明每个信号量的含义、初值和值的范围。
关系分析
同步信号
- 售票员关门 ---> 司机开车
- 司机停车 ---> 售票员开门
代码
信号量
semaphore close1 = 1, close2 = 1; // 关门同步信号量 semaphore open1 = 0, open2 = 0; // 开门信号量
司机
void driver() { while(true) { P(close1); P(close2); // 启动车辆 // 正常行使 // 到站停车 V(open1); V(open2); } }
售票员1
void seller1() { while(true) { P(open1); // 开门 // 关门 V(close1); // 售票 } }
售票员2
void seller2() { while(true) { P(open2); // 开门 // 关门 V(close2); // 售票 } }
5.取号叫号
问题
某银行有人民币储蓄业务,有n个柜员负责,有1台取号机。每个顾客进入银行后先取一个号,若有人取号则需等他人取完后才能取。取到号后等待叫号,当一个柜员人员空闲下来就叫下一个号。试用P、V操作正确编写柜台人员和顾客进程的程序。
关系分析
互斥信号量
- 顾客取号
- 服务人员叫号
同步信号量
- 取号 --- > 等待被叫号
- 服务完 ---> 叫号
代码
信号量
semaphore mutex = 1; // 同步信号量 semaphore serviceEmpty = 3; // 柜员服务空闲信号量 semaphore serviceFull = 0; // 柜员服务满的信号量,若大于3,则表示等待人数为 n-3
顾客
void customer() { while(true) { P(mutex); // 取号 V(mutex); // 等待叫号 V(serviceFull); P(serviceEmpty); } }
柜员
void servicer() { while(true) { P(serviceFull); P(mutex); // 叫号 V(mutex); // 服务 V(serviceEmpty); } }
6.听音乐问题
问题
在一间酒吧里有三个音乐爱好者队列,第一个音乐爱好者只有随身听,第二个只有音乐磁带,第三个只有电池,而要听音乐就必须有随身听,音乐磁带和电池这三种物品。酒吧老板一次出售这三种物品中的任意两种,当一名音乐爱好者得到这三种物品并听完乐曲后,酒吧老板才能再一次出售这三种物品中任意两种,于是第二名音乐爱好者得到这三种物品。并开始听乐曲,全部买卖就这样进行下去。使用P、V操作正确解决这一买卖。
关系分析
与抽烟者问题类似
同步关系:
- 老板出售物品 --> 三个爱好者
- 爱好者使用完成 --> 老板出售下一个
代码
信号量
semaphore comeIn = 1; // 同步顾客是否来,每次只能服务一个顾客 semaphore stereo = 0; // 随身听同步信号量,初始未生产,为0 semaphore tape = 0; // 磁带听同步信号量,初始未生产,为0 semaphore battle = 0; // 电池听同步信号量,初始未生产,为0 // 标识老板是否有资源 bool stereoFlag = 0; bool tapeFlag = 0; bool battleFlage = 0;
老板
void boss() { while(true) { P(comeIn); if(stereoFlag && tapeFlag) V(battle); else if(stereoFlag && battleFlag) V(tape); else V(stereo); } }
第一个音乐爱好者:需要电池和磁带,自己有随身听
void hobby1() { while(true) { P(stereo); // 购买物品,听音乐 V(comeIn); // 我买完了,老板可以接待下一个了 } }
第二个音乐爱好者:需要电池和随身听,自己有磁带
void hobby1() { while(true) { P(tape); // 购买物品,听音乐 V(comeIn); // 我买完了,老板可以接待下一个了 } }
第三个音乐爱好者:需要随身听和磁带,自己有电池
void hobby1() { while(true) { P(battle); // 购买物品,听音乐 V(comeIn); // 我买完了,老板可以接待下一个了 } }