注意:所有的互斥信号量的使用都是配对的!!!有wait操作就必然有signal操作!!!
类型定义 用 semaphore 就行
经典的消费者生产者问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| int full=0; int empty=n; int mutex=1; Cobegin Producer();Consumer(); Coend Producer(){ while(true){ 生产者生产物品 wait(empty) wait(mutex) 放入物品 signal(mutex) signal(full) } } Consumer(){ while(true){ wait(full) wait(mutex) 消费物品 signal(mutex) signal(empty) } }
|
读者写者问题
允许多个进程同时读取一个共享对象;但是不允许一个写进程和其他读进程或者写进程同时访问一个共享对象
即保证 write 进程与其他进程互斥访问共享对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| semaphore rmutex=1,wmutex=1;
static int readcount=0; Cobegin reader();writer(); Coend reader(){ while(true){ if(readcount==0) wait(rmutex); wait(rmutex); readcount++; signal(rmutex); 读操作; wait(rmutex); readcount--; signal(rmutex); if(readcount==0) signal(wmutex); } } writer(){ while(true){ wait(wmutex); 写; signal(rmutex); } }
|
哲学家进餐问题
1 2 3 4 5 6 7 8 9 10 11 12 13
| semaphore chopsticks[5]={1,1,1,1,1}; Cobegin Eat(); Coend Eat(){ while(true){ wait(chopsticks[i]); wait(chopstick[(i+1)%5]); 吃; signal(chopstick[(i+1)%5]); signal(chopsticks[i]); } }
|
1、
n个并发进程共用一个公共变量Q,写出用信号灯的PV操作实现n个进程互斥的程序描述。
1 2 3 4 5 6 7 8 9 10 11
| int mutex=1; Cobegin P1();P2();...;Pn(); Coend Pi(){ while(true){ wait(mutex) 访问Q signal(mutex) } }
|
2、
如图1所示的进程流程图中,有8个进程合作完成某一任务,试说明这八个进程之间的同步关系,用PV操作实现之,并要求写出程序描述。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
| int s2=s3=s4=s35=s36=s37=s45=s46=s47=s28=s58=s68=0; Cobegin P1();P2()……P8(); Coend P1(){ while(1){ 执行P1; V(s2); V(s3); V(s4); } } P2(){ while(1){ P(s2); 执行P2; V(s28); } } P3(){ while(1){ P(s3); 执行P3; V(s35); V(s36); V(s37); } } P4(){ while(1){ P(s4); 执行P4; V(s45); V(s46); V(s47); } } P5(){ while(1){ P(s35); P(s45); 执行P5; V(s58); } } P6(){ while(1){ P(s36); P(s46); 执行P6; V(s68); } } P7(){ while(1){ P(s37); P(s47); 执行P7; } } P8(){ while(1){ P(s28); P(s58); P(s68); 执行P8; } }
|
3、
如图2所示,get/copy/put三进程共用两个缓冲区s、t(其大小为每次存放一个记录)。get进程负责不断把输入记录送入缓冲区s中,copy进程负责从缓冲区s中取出记录复制到缓冲区t中,而put进程负责把记录从缓冲区t中取出打印。试用PV操作实现这3个进程之间的同步。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| int fullS=0; int emptyS=1; int fullT=0; int emptyT=1; semaphore mutexS=1; semaphore mutexT=1; Cobegin get();copy();put(); Coend get(){ while(true){ wait(emptyS); wait(mutexS); 放入缓冲区s; signal(mutexS); signal(fullS); } } copy(){ while(true){ wait(fullS); wait(mutexS); 从s中取出记录; signal(mutexS); signal(emptyS); wait(emptyT); wait(mutexT); 放入缓冲区t; signal(mutexT); signal(fullT); } } put(){ while(true){ wait(fullT); wait(mutexT); 拿出数据打印; signal(mutexT); signal(emptyT); } }
|
4、
有一个阅览室,读者进入阅览室必须先在一张登记表TB上登记,该表为每一个座位设一个表目,读者离开时要消掉其登记信息,阅览室共有100个座位。请用PV操作写出进程间的同步算法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| int count=100; semaphore mutex=1; Cobegin read(); Coend read(){ while(true){ 进入阅览室; wait(count); wait(mutex); 登记; signal(mutex); 读书; wait(mutex); 撤销登记; signal(mutex); signal(count); 离开; } }
|
5、
设公共汽车上,司机和售票员的活动分别是:
司机的活动:启动车辆、正常行车、到站停车
售票员的活动:开车门、售票、关车门
在汽车不断到站、停站、行驶过程中,这两个活动有什么同步关系?请用信号量的PV操作实现。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| int s1=0; int s2=0; Cobegin driver();seller(); Coend driver(){ while(true){ wait(s2); 启动车辆; 正常行车; 到站停车; signal(s1); } } seller(){ while(true){ wait(s1); 开车门; 售票; 关车门; signal(s2); } }
|
6、
医生为某病员诊病,认为需要做些化验,于是,就为病员开出化验单,病员取样送到化验室,等待化验完毕交回化验结果,然后继续诊病。医生为病员诊病和化验分别是两个协作的进程。试用信号灯的PV操作描述这两个进程之间的同步。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| int s1=0; int s2=0; 医生诊病(){ while(1){ 诊病; V(S1); P(S2); 诊病; } } 化验(){ while(1){ P(S1); 化验; V(S2); } }
|
7、
有个仓库,可以放A和B两种产品,仓库的存储空间足够大,但要求:
(1)一次只能放入一种产品(A或B)
(2)-N<A产品数量-B产品数量<M
其中,M和N是正整数,试用PV操作描述产品A和产品B的入库过程。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| int Sa=M-1; int Sb=N-1; int mutex=1; Cobegin 存放A();存放B(); Coend 存放A(){ while(1){ P(Sa); P(mutex); 放入A; V(mutex); V(Sb); } } 存放B(){ while(1){ P(Sb); P(mutex); 放入B; V(Sa); V(mutex); } }
|
8、
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| int capacity=500; int mutex=1; Cobegin Visit(); Coend Visit(){ while(true){ wait(capacity); wait(mutex); 进门 signal(mutex); 参观; wait(mutex); 出门; signal(mutex); signal(capacity); } }
|
9、
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| int A1=x; int A2=M-x; int B1=y; int B2=N-y; int mutexA=1; int mutexB=1; Cobegin A();B(); Coend A(){ while(true){ wait(A1); wait(mutexA); 从A的信箱中取出一个信件; signal(mutexA); signal(A2); 回答问题并提出一个新问题; wait(B2); wait(mutexB); 将新邮件装入B邮箱; signal(mutexB); signal(B1); } } B(){ while(true){ wait(B1); wait(mutexB); 从B的信箱中取出一个信件; signal(mutexB); signal(B2); 回答问题并提出一个新问题; wait(A2); wait(mutexA); 将新邮件装入A邮箱; signal(mutexA); signal(A1); } }
|
10、
三个进程 P1、P2、P3 互斥使用一个包含 N(N>0)个单元的缓冲区。P1 每次用 produce() 生成一个正整数并用put()送入缓冲区某一个空单元中;P2 每次用 getodd()从该缓冲区中取出一个奇数并用 countodd()统计奇数个数;P3 每次用 geteven()从该缓冲区中取出一个偶数并用 counteven()统计偶数个数。请用信号量机制实现这三个进程的同步与互斥活动, 并说明所定义的信号量的含义。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| semaphore mutex=1; int empty=N; int odd=0; int even=0; Cobegin P1();P2();P3() Coend P1(){ while(true){ wait(empty); wait(mutex); produce(); put(); signal(mutex); if(num&1) signal(odd); else signal(even); } } P2(){ while(true){ wait(odd); wait(mutex); getodd(); countodd()++; signal(mutex); signal(empty); } } P3(){ while(true){ wait(even); wait(mutex); geteven(); counteven()++; signal(mutex); signal(empty); } }
|
11、
一个野人部落从一个大锅中一起吃炖肉,这个大锅一次可以存放 M 人份的炖肉。当野人们想吃的时候,如果锅中不空,他们就自助着从大锅中吃肉。如果大锅空了,他们就叫 醒厨师,等待厨师再做一锅肉。 野人线程未同步的代码如下: while (true){ getServingFromPot() } 厨师线程未同步的代码如下: while (true) { putServingsInPot(M) } 同步的要求是: 当大锅空的时候,野人不能够调用 getServingFromPot() 仅当大锅为空的时候,大厨才能够调用 putServingsInPot() 问题:请写出使用 PV 满足同步要求的完整程序。
野人互斥着吃,厨师互斥着做
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| semaphore mutex=1; semaphore full=0; semaphore empty=0; static int servings=0; Cobegin cook();eat(); Coend cook(){ while(true){ wait(empty); wait(mutex); putServingsInPot(M); servings += M; signal(mutex); signal(full); } }
eat(){ while(true){ wait(full); wait(mutex); getServingFromPot(); servings -= 1; signal(mutex); if(servings == 0) signal(empty); } }
|
12、
机场中有些道路,航班和摆渡车都可以通行。当航班通行时,摆渡车必须等待,直到所有航班通过后才能通行。当摆渡车通行时,航班必须等待,直到所有摆渡车通过后才能通行。请用信号量描述摆渡车和航班通行的控制过程。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| semaphore mutex=1; semaphore plane=1,car=1; int plane_count=0;,car_count=0; Cobegin Car();Plane(); Coend Car(){ while(true){ if(car_count==0) wait(car); car_count++; wait(mutex); 开车! signal(mutex); car_count--; if(car_count==0) signal(plane); } } Plane(){ ... }
|