viod main() {
Semaphore fulln=fullm=0; Semaphore emptyn=n; Semaphore emptym=m;
Int in_n=in_m=out_n=out_m=0; Int buffer_n [n],buffer_m [m]; CoBegin {
P(); Q(); R(); }
CoEnd }
viod P () {
While (true ) {
……………..
Produce an item in nextp; P(emptyn);
Buffer_n [in_n]=nextp; in_n=(in_n+1)%n; V(fulln); } }
viod Q() {
While (true ) {
P(fulln);
nextc=buffer_n [out_n]; out_n=(out_n+1)%n;
V(emptyn);
Consume the item in nextc; …………..
Produce an item in nextp; P(emptym);
buffer_m [in_m]= nextp; in_m=(in_m+1)%m; V(fullm);
}
}
viod R() {
while(ture) {
P(fullm);
nextc=buffer_m [out_m]; out_m=(out_m+1)%m; V(emptym);
Consume the item in nextc; } }
4-8考虑一个理发店,只有一个理发师,只有N张可供顾客等待理发的椅子,如果没有顾客,则理发师睡觉;如果有一顾客进入理发店发现理发师在睡觉,则把他叫醒,写一程序协调理发师和顾客之间的关系。
设S1表示空椅子个数,初始为N, S2表示理发店中顾客个数,初始为0;
A进程表示顾客进入理发店(前提有空椅子) B进程表示理发店一个顾客工作
A进程 B进程
While (True){ P(S1); P(S2); V(S2); ┋ 理发师给用户理发 ┋ 顾客坐入椅子 V(S1);}
Void barber(void) { while (true) { P(customers); P(mutex);
waiting = waiting – 1 ; V(barber); V(mutex); cut_hair( ); }
顾客进程
Void customers(void) {P(mutex);
if(waiting { waiting = waiting + 1 ; V(customers); V(mutex); P(barbers); get_hair( );} else {V(mutex);} } 4-9 一个二元信号量是一个其值只能取0,1的信号量,给出一个二元信号量实现一般信号量P、V操作的程序。 一个二元信号量的值只能是0或1,二元信号量的定义: p(s):if(s==1)s=0; else 将进程放入等待队列 v(s):if(队列为空)s=1; else 将等待队列队首进程移出并放入就绪队列 本题使用两个二元信号量及一个变量: m用来互斥访问变量c,初值为1。 b用来代替信号量S,初值为0。将应挂在信号量S上的进程挂在b上。 c中存放信号量S的值 用二元信号量实现一般信号量S的描述如下: P(S) { P(m); c=c-1; if(c<0){ V(m); P(b):} else V(m); } V(S) { P(m); c=c+1; if(c<=0) V(b): V(m); } 4-11在一个系统中,若进程之间除了信号量之外不能共享任何变量,进程之间能互相通信吗? 答:能,同步与互斥是进程通信的基本内容,P、V操作与信号量结合可以实现同步与互斥。 4-12有一个阅览室,共有100个座位,读者进入时必须先在一张登记表上登记,该表为每一座位列一表目,包括座号和读者姓名等,读者离开时要消掉登记的信息,试问: (1)为描述读者的动作,应编写几个程序,设置几个进程? (2)试用PV操作描述读者进程之间的同步关系。 答:读者的动作有两个,一是填表进入阅览室,这时要考虑阅览室里是否有座位;一是读者阅读完 毕,离开阅览室,这时的操作要考虑阅览室里是否有读者。读者在阅览室读书时,由于没有引起资 源的变动,不算动作变化。 算法的信号量有三个: seats——表示阅览室是否有座位(初值为100,代表阅览室的空座位数); readers——表示阅览室里的读者数,初值为0; 用于互斥的mutex,初值为1。 读者进入阅览室的动作描述 getin: while(TRUE){ P (seats); /*没有座位则离开*/ P(mutex)进入临界区*/ 填写登记表; 进入阅览室读书; V(mutex) /*离开临界区*/ V(readers) } 读者离开阅览室的动作描述 getout: while(TRUE){ P(readers) /*阅览室是否有人读书*/ P(mutex) /*进入临界区*/ 消掉登记; 离开阅览室; V(mutex) /*离开临界区*/ V(seats) /*释放一个座位资源*/ } 4-13写一个无死锁、无饥饿的哲学家进餐问题的解。 ? 5个哲学家围坐在圆桌边。每人前面有一支筷子。当一个哲学家思考时,他不影响 其他同事。一段时间后,他需要用餐了,而且试图拿到最靠近他的两支筷子。当他拿到两支筷子后,就开始用餐。用毕放下筷子,重新开始思考。 ? 死锁:当5个人同时拿自己左边的一支筷子。再要拿右边的筷子时。他们的要求会 被无休止的推迟。这就发生了死锁。 ? 饥饿:当5个人同时拿自己左边的一支筷子,看到右边不可用。同时放下自己左边 的一支筷子。等一会,又同时拿起右边的筷子。这样不停忙着。但都无法进展。就发生了饥饿。 void main() { static semaphore chopstick[5]={1,1,1,1,1}; Cobegin philosopher(0); philosopher(1); philosopher(2); philosopher(3); philosopher(4); Coend } void philosopher(int i) { while(ture) { if(i%2==0) { p(chopstick[i]); p(chopstick[(i+1)%5]); } else { p(chopstick[(i+1)%5]); p(chopstick[i]); } ...... eating; ...... v(chopstick[i]); v(chopstick[(i+1)%5]); thinking...... } } 4-14设有一个具有N个信息元素的环形缓冲区,A进程顺序地把信息写入缓冲区,B进程依次地从缓冲区中读出信息。回答下列问题: (1)叙述A、B两个进程的相互制约关系。 (2)用P、V操作表示A、B进程的同步算法。 [答] (1)A和B两个进程的相互制约关系是既有互斥又有同步:对缓冲区的访问必须互斥,并且当缓冲区满时,A进程不可以写,必须等待;当缓冲区空时,B进程不可以读,必须等待。 (2)用P、V操作表示A、B进程的同步算法如下: BEGIN Buffer: ARRAY [0..N-1] of integer; m, out: Integer; S0,S1,S2: Semaphore;