收藏 分享(赏)

信号量答案.docx

上传人:weiwoduzun 文档编号:5722275 上传时间:2019-03-14 格式:DOCX 页数:12 大小:28.55KB
下载 相关 举报
信号量答案.docx_第1页
第1页 / 共12页
信号量答案.docx_第2页
第2页 / 共12页
信号量答案.docx_第3页
第3页 / 共12页
信号量答案.docx_第4页
第4页 / 共12页
信号量答案.docx_第5页
第5页 / 共12页
点击查看更多>>
资源描述

1、第一部分2、该方法对可抢占调度完全没问题。事实上,它就是为这种情况设计的。当调度为不可抢占的,该方法将会失败。假设 turn 初值为 0,而进程 1 首先运行。它将一直循环,永不释放 CPU。3、对于内核线程,线程可以在信号量上阻塞,而内核可以运行该进程中的其它线程。因而,使用信号量没有问题。而对于用户级线程,当某个线程在信号量上阻塞时,内核将认为整个进程都被阻塞,而且不再执行它。因此,进程失败。4、某商店有两种食品 A 和 B, 最大数量各为 m 个。该商店将 A、B 两种食品搭配出售,每次各取一个。为避免食品变质,遵循先到食品先出售的原则。有两个食品公司分别不断地供应A、B 两种食品(每次

2、一个)。为保证正常销售,当某种食品的数量比另一种的数量超过 k(k 小于m)个时,暂停对数量大的食品进货。试用 P、V 操作解决上述问题中的同步和互斥关系。4、参考答案#define Max m /*最大数量*/typedef int semaphore;/*初始化*/semaphore A_full = 0; /*商店中 A 食品数目 假设初始值为 0*/semaphore B_full = 0; /*商店中 B 食品数目 假设初始值为 0*/semaphore A_empty = Max; /* A 可缓冲数目 */semaphore B_empty = Max; /* B 可缓冲数目 *

3、/semaphore A_minus_B = k; /* 商店中 A 超过 B 的数目 初始值为 k-(A_full B_full) */semaphore B_minus_A = k;/* 商店中 B 超过 A 的数目 初始值为 k- (B_full A_full) */Queue Q_A,Q_B; /*先进先出的队列模拟商店中两食品资源*/semaphore QA_mutex = 1; /*队列 A 互斥量*/semaphore QB_mutex = 1; /*队列 B 互斥量*/* 商店搭配出售 A B 进程*/void Shop_A_B () /*商店出售 A B 进程 两食品搭配出售

4、*/A a;B b;while(1)P(A_full);P(B_ful);P(QA_mutex);a = Q_A.remove_item(); /*从商店中取出 A*/V(QA_mutext);P(QB_mutex)b = Q_B.remove_item();/*从商店中取出 B*/V(QB_mutex);V(A_empty);V(B_empty);sell(a,b); /*卖出 a,b*/*总结:相当于生产者消费者问题中的消费者,首先执行将 A,B 中的空槽减一,然后开始临界区操作,此处分别有两种商品,因此分别有 QA-mutex 和 QB_mutex 两个互斥量。同时,为满足题目中先到先出

5、的要求,采用队列的方式取出商品。完成临界区操作后,执行 V(A_empty)和 V(B_empty)操作。*/*食品公司向商店提供 A 进程*/void Stock_A() /*进货 A*/A a;while(1)a = getA();P(A_empty);P(A_minus_B); /the key of this problemP(QA_mutex);Q_A.insert_item(a);V(QA_mutex);V(A_full);V(B_minus_A);/*总结:相当于生产者消费者问题中的生产者,每次先生产一个产品,首先将空槽的数量减少一个,由于 A 产品数量增加了一个,所以 A 减

6、B 的量的允许值也少了一个(与 k 比较) 。然后开始临界区操作,使用 QA_mutex 来对 A 产品有关的临界区访问进行互斥。最后将满槽的数目加一,由于 B 相对于 A 减一,故允许的 B 减 A 的差值加一*/*食品公司向商店提供 B 进程*/void Stock_B() /*进货 B*/B b;While(1)b = getB();P(B_empty);P(B_minus_A);P(QB_mutex);Q_B.insert_item(b);V(QB_mutex);V(B_full);V(A_minus_B);第 4 题总结:(1 )主要是模仿生产者消费者问题,相当于两个生产者一个消费者

7、的问题(2)涉及到了两个不同商品的临界区访问,主要是确定临界区操作所涉及的具体对象。同时,当涉及先进先出问题时,优先考虑队列操作5、考虑具有如下特征的共享资源:(1)当使用该资源的进程小于 3 个时,新申请资源的进程可以立刻获得资源;(2)当三个资源都被占用后,只有当前使用资源的三个进程都释放资源后,其他申请资源的进程才能够获得资源。由于需要使用计数器来记录有多少进程正在使用资源和等待资源,而这些计数器自身也需要互斥执行修改动作的共享资源,所以可以采用如下的程序:1 semaphore mutex = 1, block = 0; 2 int active = 0, waiting = 0; 3

8、 boolean must_wait = false; 45 semWait(mutex); 6 if(must_wait) 7 +waiting; 8 semSignal(mutex); 9 semWait(block); /不能在互斥区执行 block10 semWait(mutex); 11 -waiting; 12 13 +active; 14 must_wait = active = 3; 15 semSignal(mutex); 1617 /* 临界区:对获得的资源进行操作 */1819 semWait(mutex); 20 -active; 21 if(active = 0) 2

9、2 int n;23 if (waiting 0 ) 26 semSignal(block);27 -n;28 29 must_wait = false; 30 31 semSignal(mutex); 这个程序看起来没有问题:所有对共享数据的访问均被临界区所保护,进程在临界区中执行时不会自己阻塞,新进程在有三个资源使用者存在时不能使用共享资源,最后一个离开的使用者会唤醒最多 3 个等待着的进程。a这个程序仍不正确,解释其出错的位置;b假如我们将第六行的 if 语句更换为 while 语句,是否解决了上面的问题?有什么难点仍然存在?a.第 29 行直接让 must_wait=false 有问题

10、,因为随后可能会有另一个新进程来访问资源,并在第六行判断为 false,进而获取资源,而此时可能已经有 3 个等待的进程被唤醒,所以在同一时间内可能会有超过 3 个进程进入临界区。b.可以解决上述问题,但是会有另一个缺陷,那就是先来的进程可能会在后来的进程之后获得资源,甚至有可能一直阻塞而饥饿。总结:没有太大收获,总之互斥量 mutex 的 P 操作和 V 操作之间不会被其他进程所干扰,一次必须执行完。Block 操作不能在一个互斥量所保护的临界区中执行,即不能在临界区中出现可能引起阻塞的过程,否则会发生死锁。当某进程可能在等待过程中被后来进程插队进入临界区时,可能发生饥饿现象6、现在考虑上一

11、题的正确解法,如下:1 semaphore mutex = 1, block = 0; 2 int active = 0, waiting = 0; 3 boolean must_wait = false; 45 semWait(mutex); 6 if(must_wait) 7 +waiting; 8 semSignal(mutex); 9 semWait(block); 10 else 11 +active; 12 must_wait = active = 3; 13 semSignal(mutex); 14 1516 /* 临界区:对获得的资源进行操作 */1718 semWait(mu

12、tex); 19 -active; 20 if(active = 0) 21 int n;22 if (waiting 0 ) 27 semSignal(block); /* */28 -n;29 30 must_wait = active = 3; 31 32 semSignal(mutex); a解释这个程序的工作方式,为什么这种工作方式是正确的?b这个程序不能完全避免新到达的进程插到已有等待进程前得到资源,但是至少使这种问题的发生减少了。给出一个例子;c这个程序是一个使用信号量实现并发问题的通用解法样例,这种解法被称作“Ill Do it for You”(由释放者为申请者修改计数器)模

13、式。解释这种模式。a.这个程序在释放的部分维护 active 的值,第 30 行 must_wait = active = 3;确保了等在 block上的进程和新来的进程不会同时进入临界区。b 仍然会有插队的情况,在一个进程执行完:8 semSignal(mutex);这一句但还没有执行:9 semWait(block);这时可能会有一个新的进程获取 mutex,并阻塞在 block 上。如果此时有离开临界区的进程唤醒等在 block 上的进程,那么后来的进程可能会先执行,先来的进程却仍阻塞在 block 上。c “Ill Do it for You”由离开的进程来修改全局变量并唤醒阻塞的进程

14、。这样被唤醒的进程不用再次判断全局条件是否满足。可以控制进程并发度。7、现在考虑上一题的另一个正确解法,如下:1 semaphore mutex = 1, block = 0; 2 int active = 0, waiting = 0; 3 boolean must_wait = false; 45 semWait(mutex); 6 if(must_wait) 7 +waiting; 8 semSignal(mutex); 9 semWait(block); /在一个进程即将被阻塞时,必须先释放掉互斥锁10 -waiting; 11 12 +active; 13 must_wait = a

15、ctive = 3; 14 if(waiting 0 1617 else semSignal(mutex); 1819 /* 临界区:对获得的资源进行操作 */2021 semWait(mutex); 22 -active; 23 if(active = 0) /只有在 must_wait 为 true 的时候才可能到这一步,这时候必须等所有进程全部释放资源24 must_wait = false; 25 if(waiting = 0 /如果不是必须等待且有等待进程,则唤醒一个2728 else semSignal(mutex); a解释这个程序的工作方式,为什么这种工作方式是正确的?b这个方

16、法在可以同时唤醒进程个数上是否和上一题的解法有所不同?为什么?c这个程序是一个使用信号量实现并发问题的通用解法样例,这种解法被称作“Pass the Paton”(接力棒传递)模式。解释这种模式。a.进程在释放资源时,如果此时释放的是最后一个被占用的资源,那么会唤醒一个等待在 block上的进程(如果有的话) ,这个被唤醒的进程会判断是否还有等待在 block 上的进程并唤醒,直到有三个唤醒的进程。在这一过程中,新的申请资源的进程会等待在 mutex 上,而刚才第三个被唤醒的进程会唤醒等在 mutex 上的一个进程。b.这个方法是唤醒一个进程,接着由该进程唤醒第二个进程,再由第二个进程唤醒第三

17、个进程。之前的方法是由一个进程同时唤醒三个进程。c.释放者只唤醒一个进程,然后被唤醒的进程负责唤醒下一个进程直到唤醒所有等待的进程或唤醒的进程数量达到上限。接力棒模式能避免插队,但是在进程的并发性上不如“Ill Do it for You”。8、由于水面高度不同,有 160175 米的落差,所以三峡大坝有五级船闸,T1T5。由上游驶来的船需经由各级船闸到下游;由下游驶来的船需经由各级船闸到上游。假设只能允许单方向通行(此假设与实际情况不符,实际为双向各五级船闸) 。 试用 P、V 操作正确解决三峡大坝船闸调度问题。8、参考答案五级船闸,每级只能容纳一艘船。一边已经有船等待时,另一边新来的船也不

18、能出发。int inside=0, up_waiting=0, down_waiting=0;Semaphore up_block=0, down_block=0, big_lock=1;Semaphore r5 = 1,1,1,1,1;/船闸之间互斥void down()down(big_lock)if(up_waiting0)+down_waiting; /前面有船等待,则继续等待up(big_lock);down(down_block);else+inside;up(big_lock);/依次通过船闸,每个船闸最多容纳一艘船int i=0;down(r0); /申请通过第一级船闸whil

19、e(i 1) V(mutex);P(waiting); else V(mutex);V(barber);理发;P(mutex);count = count 1;if (count0) V(waiting);V(mutex); 理发师:while (true) P(barber);理发;12、推广的消息缓冲问题消息缓冲区为 k 个,有 m 个发送进程,n 个接收进程,每个接收进程对发送来的消息都必须取一次。试用 P、V 操作解决发送进程和接受进程之间的正确通信问题。解答:mutex_bufferk;/同步:读完再写;互斥:只有一个 Sender 使用某个 buffer。初始化为1。bufferk

20、;/缓冲区。初始化为 1countk;/未读数目。初始化为 0。mutex_readkn;/同步:先写后读。初始化为 0。next;/下一个写缓冲区。初始化为 0mutex_next;/互斥:只有一个 Sender 使用 next。初始化为 1。Sender()while(have_message)P(mutex_next); /每次只有一个 sender 可以申请发送 有什么区别?cur=next; next=(next+1)%k; /next 的值发生了改变V(mutex_next);P(mutex_buffercur); /申请想 buffercur中写write(buffercur);

21、for(i=0;icountcur=n;Receiver()id=myID();for(i=0;1;i=(i+1)%k)P(mutex_readiid);read(bufferi);counti-;if(counti=0) V(mutex_bufferi);13、第二类读者写者问题(写者优先)试用信号量及 P、V 操作解决写者优先问题,要求:a. 多个读者可以同时进行读;b. 写者必须互斥(只允许一个写者写,也不能读者写者同时进行 );c. 写者优先于读者(一旦有写者,则后续读者必须等待,唤醒时优先考虑写者) 。解答:Semaphore mutex1=1, mutex2=1, mutex3=1

22、, read=1, write=1;void reader()P(mutex3);/保证最多有一个读者等在 read 上,避免等待在 read 上的写者与多个读者竞争P(read); /?外面两层主要是干嘛用的P(mutex1); /mutex1 主要用于对于 readcount 的访问readcount+;if (readcount=1)P(write); /阻塞写者,或者已经有写者,则自己被阻塞V(mutex1);V(read);V(mutex3);reading;P(mutex1);readcount-;if (readcount=0)V(write);V(mutex1);void wr

23、iter()P(mutex2);writecount+;if (writecount=1)P(read);V(mutex2);P(write);writing;V(write);P(mutex2);writecount-;if (writecount=0)V(read);V(mutex2);14、有一个系统,定义 P、V 操作如下:P(s):s.count -;if s0 then 将本进程插入相应队列末尾等待;V(s):s.count +;if s=0 then 从相应等待队列队尾唤醒一个进程,将其插入就绪队列;回答问题:a. 这样定义 P、 V 操作是否有问题?b. 用这样的 P、 V 操

24、作实现 N 个进程竞争使用某一共享变量的互斥机制。c. 对于 b 的解法,有无效率更高的方法。如有,试问降低了多少复杂性?a.后进先出的等待队列,可能引起饥饿b.定义 Semaphore mN-1, m1=N-1, m2=N-2,mN-1=1,然后进程依次 P 从 m1到mN-1,V 的时候顺序相反,这样使每个信号量上最多只等待一个进程,进程访问共享变量的顺序就与进程等待的顺序一致,先到先得,从而可以避免饥饿。第二部分2、其实现的代价很高。每次在某些等待变化的进程的条件中出现的任何变量,runtime 系统都必须重新计算该条件,以判断该进程是否能够被解锁。而对于 Hoare 和 Brinch Hansen 管程,则只需 signal 原语即可唤醒进程(第二版答案 2-28)3、需要互斥的几个进程在进入临界区之前 receive 同一个进程,该进程在一次访问临界资源的过程之前只 send 一个 msg,这样就可以保证互斥操作。4、用 receive 模拟 P 操作,用 send 模拟 V 操作。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 企业管理 > 管理学资料

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报