ps大神这个图片ps能不能打开cdr改成一张女的往左站着

&&&&哲学家进餐问题的C语言实现
哲学家进餐问题的C语言实现
这是一个描叙哲学家进餐问题的代码。。。。。。C语言写额
若举报审核通过,可奖励20下载分
被举报人:
sqysqy123456
举报的资源分:
请选择类型
资源无法下载
资源无法使用
标题与实际内容不符
含有危害国家安全内容
含有反动色情等内容
含广告内容
版权问题,侵犯个人或公司的版权
*详细原因:
VIP下载&&免积分60元/年(1200次)
您可能还需要
开发技术下载排行操作系统哲学家进餐问题_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
操作系统哲学家进餐问题
上传于||文档简介
&&死​锁​是​进​程​并​发​执​行​过​程​中​可​能​出​现​的​现​象​,​所​谓​死​锁​,​是​指​多​个​进​程​在​运​行​过​程​中​因​争​夺​资​源​而​造​成​的​一​种​僵​局​。​哲​学​家​就​餐​问​题​是​描​述​死​锁​的​经​典​例​子​。​为​了​防​止​死​锁​,​可​以​采​用​资​源​预​分​配​法​或​者​资​源​按​序​分​配​法​。
阅读已结束,如果下载本文需要使用1下载券
想免费下载本文?
定制HR最喜欢的简历
下载文档到电脑,查找使用更方便
还剩8页未读,继续阅读
定制HR最喜欢的简历
你可能喜欢用C语言实现P、V操作_仙剑宝宝吧_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0可签7级以上的吧50个
本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:16贴子:
用C语言实现P、V操作
操作系统并发和互斥:和理发师问题 : (1) 在什么情况下5 个哲学家全部吃不上饭? 考虑两种实现的方式,如下: A. 算法描述: void philosopher(int i) /*i:哲学家编号,从0 到4*/ { while (TRUE) { think( ); /*哲学家正在思考*/ take_fork(i); /*取左侧的筷子*/ take_fork((i+1) % N); /*取左侧筷子;%为取模运算*/ eat( ); /*吃饭*/ put_fork(i); /*把左侧筷子放回桌子*/ put_fork((i+1) % N); /*把右侧筷子放回桌子*/ } } 分析:假如所有的哲学家都同时拿起左侧筷子,看到右侧筷子不可用,又都放下左侧筷子, 等一会儿,又同时拿起左侧筷子,如此这般,永远重复。对于这种情况,即所有的程序都在 无限期地运行,但是都无法取得任何进展,即出现饥饿,所有哲学家都吃不上饭。 B. 算法描述: 规定在拿到左侧的筷子后,先检查右面的筷子是否可用。如果不可用,则先放下左侧筷子, 等一段时间再重复整个过程。 分析:当出现以下情形,在某一个瞬间,所有的哲学家都同时启动这个算法,拿起左侧的筷 子,而看到右侧筷子不可用,又都放下左侧筷子,等一会儿,又同时拿起左侧筷子……如此 这样永远重复下去。对于这种情况,所有的程序都在运行,但却无法取得进展,即出现饥饿, 所有的哲学家都吃不上饭。 (2) 描述一种没有人饿死(永远拿不到筷子)算法。 考虑了四种实现的方式(A、B、C、D): A.原理:至多只允许四个哲学家同时进餐,以保证至少有一个哲学家能够进餐,最终总会释 放出他所使用过的两支筷子,从而可使更多的哲学家进餐。以下将room 作为信号量,只允 许4 个哲学家同时进入餐厅就餐,这样就能保证至少有一个哲学家可以就餐,而申请进入 餐厅的哲学家进入room 的等待队列,根据FIFO 的原则,总会进入到餐厅就餐,因此不会 出现饿死和的现象。 伪码: semaphore chopstick[5]={1,1,1,1,1}; semaphore room=4; void philosopher(int i) { while(true) { think(); wait(room); //请求进入房间进餐 wait(chopstick[i]); //请求左手边的筷子 wait(chopstick[(i+1)%5]); //请求右手边的筷子 eat(); signal(chopstick[(i+1)%5]); //释放右手边的筷子 signal(chopstick[i]); //释放左手边的筷子 signal(room); //退出房间释放信号量room } } B.原理:仅当哲学家的左右两支筷子都可用时,才允许他拿起筷子进餐。 方法1:利用AND 型实现:根据课程讲述,在一个原语中,将一段代码同时需 要的多个临界资源,要么全部分配给它,要么一个都不分配,因此不会出现的情形。当 某些资源不够时阻塞调用进程;由于等待队列的存在,使得对资源的请求满足FIFO 的要求, 因此不会出现饥饿的情形。 伪码: semaphore chopstick[5]={1,1,1,1,1}; void philosopher(int I) { while(true) { think(); Swait(chopstick[(I+1)]%5,chopstick[I]); eat(); Ssignal(chopstick[(I+1)]%5,chopstick[I]); } } 方法2:利用信号量的保护机制实现。通过信号量mutex对eat()之前的取左侧和右侧筷 子的操作进行保护,使之成为一个原子操作,这样可以防止的出现。 伪码: semaphore mutex = 1 ; semaphore chopstick[5]={1,1,1,1,1}; void philosopher(int I) { while(true) { think(); wait(mutex); wait(chopstick[(I+1)]%5); wait(chopstick[I]); signal(mutex); eat(); signal(chopstick[(I+1)]%5); signal(chopstick[I]); } }
3D双端东方魔幻网游「大青云」勾魂公测,穿越逆转,封神故事,全新演绎!
C. 原理:规定奇数号的哲学家先拿起他左边的筷子,然后再去拿他右边的筷子;而偶数号 的哲学家则相反.按此规定,将是1,2号哲学家竞争1号筷子,3,4号哲学家竞争3号筷子.即 五个哲学家都竞争奇数号筷子,获得后,再去竞争偶数号筷子,最后总会有一个哲学家能获得两支筷子而进餐。而申请不到的哲学家进入阻塞等待队列,根FIFO原则,则先申请的哲 学家会较先可以吃饭,因此不会出现饿死的哲学家。 伪码: semaphore chopstick[5]={1,1,1,1,1}; void philosopher(int i) { while(true) { think(); if(i%2 == 0) //偶数哲学家,先右后左。 { wait (chopstick[ i + 1 ] mod 5) ; wait (chopstick[ i]) ; eat(); signal (chopstick[ i + 1 ] mod 5) ; signal (chopstick[ i]) ; } Else //奇数哲学家,先左后右。 { wait (chopstick[ i]) ; wait (chopstick[ i + 1 ] mod 5) ; eat(); signal (chopstick[ i]) ; signal (chopstick[ i + 1 ] mod 5) ; } } D.利用管程机制实现(最终该实现是失败的,见以下分析): 原理:不是对每只筷子设置信号量,而是对每个哲学家设置信号量。test()函数有以下作 用: a. 如果当前处理的哲学家处于饥饿状态且两侧哲学家不在吃饭状态,则当前哲学家通过 test()函数试图进入吃饭状态。 b. 如果通过test()进入吃饭状态不成功,那么当前哲学家就在该信号量阻塞等待,直到 其他的哲学家进程通过test()将该哲学家的状态设置为EATING。 c. 当一个哲学家进程调用put_forks()放下筷子的时候,会通过test()测试它的邻居, 如果邻居处于饥饿状态,且该邻居的邻居不在吃饭状态,则该邻居进入吃饭状态。 由上所述,该算法不会出现,因为一个哲学家只有在两个邻座都不在进餐时,才允 许转换到进餐状态。 该算法会出现某个哲学家适终无法吃饭的情况,即当该哲学家的左右两个哲学家交替 处在吃饭的状态的时候,则该哲学家始终无法进入吃饭的状态,因此不满足题目的要求。 但是该算法能够实现对于任意多位哲学家的情况都能获得最大的并行度,因此具有重要 的意义。 伪码: #define N 5 /* 哲学家人数*/ #define LEFT (i-1+N)%N /* i的左邻号码 */ #define RIGHT (i+1)%N /* i的右邻号码 */ typedef enum { THINKING, HUNGRY, EATING } phil_ /*哲学家状态*/ monitor dp /*管程*/ { phil_state state[N]; semaphore mutex =1; semaphore s[N]; /*每个哲学家一个信号量,初始值为0*/ void test(int i) { if ( state[i] == HUNGRY &&state[LEFT(i)] != EATING && state[RIGHT(i)] != EATING ) { state[i] = EATING; V(s[i]); } } void get_forks(int i) { P(mutex); state[i] = HUNGRY; test(i); /*试图得到两支筷子*/ V(mutex); P(s[i]); /*得不到筷子则阻塞*/ } void put_forks(int i) { P(mutex); state[i]= THINKING; test(LEFT(i)); /*看左邻是否进餐*/ test(RIGHT(i)); /*看右邻是否进餐*/ V(mutex); } } 哲学家进程如下: void philosopher(int process) { while(true) { think(); get_forks(process); eat(); put_forks(process); } }
2.理发师问题:一个理发店有一个入口和一个出口。理发店内有一个可站5 位顾客的站席 区、4 个单人沙发、3 个理发师及其专用理发工具、一个收银台。新来的顾客坐在沙发上等 待;没有空沙发时,可在站席区等待;站席区满时,只能在入口外等待。理发师可从事理 发、收银和休息三种活动。理发店的活动满足下列条件: 1)休息的理发师是坐地自己专用的理发椅上,不会占用顾客的沙发; 2)处理休息状态的理发师可为在沙发上等待时间最长的顾客理发; 3)理发时间长短由理发师决定; 4)在站席区等待时间最长的顾客可坐到空闲的理发上; 5)任何时刻最多只能有一个理发师在收银。 试用信号量机制或管程机制实现理发师进程和顾客进程。 原理: (1)customer 进程: 首先检查站席区是否已满(stand_capacity),若满选择离开,否则进入站席区,即进入 理发店。在站席区等待沙发的空位(信号量sofa),如果沙发已满,则进入阻塞等待队列, 直到出现空位,在站席区中等待时间最长的顾客离开站席区(stand_capacity)。坐到沙 发上,等待理发椅(barber_chair),如果理发椅已满,则进入阻塞等待队列,直到出现 空位,在沙发上等待时间最长的顾客离开沙发(释放信号量sofa)。坐到理发椅上,释放 准备好的信号(customer_ready),获得该理发师的编号(0~1 的数字)。等待理发师理 发结束(finished[barber_number])。在离开理发椅之前付款(payment),等待收据 (receipt),离开理发椅(leave_barberchair)。最后离开理发店。 这里需要注意几点: a) 首先是几个需要进行互斥处理的地方,主要包括:进入站席区、进入沙发、进入理发椅 和付款几个地方。 b) 通过barber_chair 保证一个理发椅上最多只有一名顾客。但这也不够,因为单凭 baber_chair 无法保证一名顾客离开理发椅之前,另一位顾客不会坐到该理发椅上, 因此增加信号量leave_barberchair,让顾客离开理发椅后,释放该信号,而理发 师接收到该信号后才释放barber_chair 等待下一位顾客。 c) 在理发的过程中,需要保证是自己理发完毕,才能够进行下面的付款、离开理发椅的活 动。这个机制是通过customer 进程获得给他理发的理发师编号来实现的,这样,当 该编号的理发师释放对应的finished[i]信号的时候,该顾客才理发完毕。 d) 理发师是通过mutex 信号量保证他们每个人同时只进行一项操作(理发或者收款)。 e) 为了保证该顾客理发完毕后马上可以付款离开,就应该保证给该顾客理发的理发师在理 发完毕后马上到收银台进入收款操作而不是给下一位顾客服务。在伪码中由以下机制实 现:即顾客在释放离开理发椅的信号前,发出付款的信号。这样该理发师得不到顾客的 离开理发椅的信号,不能进入下一个循环为下一名顾客服务,而只能进入收款台的收款 操作。直到顾客接到收据后,才释放离开理发椅的信号,离开理发椅,让理发师释放该 理发椅的信号,让下一位等待的顾客坐到理发椅上。 (2)barber 进程 首先将该理发师的编号压入队列,供顾客提取。等待顾客坐到理发椅坐好(信号量 customer_ready),开始理发,理发结束后释放结束信号(finished[i])。等待顾客 离开理发椅(leave_barberchair)(期间去收银台进行收款活动),释放理发椅空闲信 号(barber_chair),等待下一位顾客坐上来。 (3)cash(收银台)进程 等待顾客付款(payment),执行收款操作,收款操作结束,给付收据(receipt)。 信号量总表: 信号量 wait signal stand_capacity 顾客等待进入理发店 顾客离开站席区 sofa 顾客等待坐到沙发 顾客离开沙发 barber_chair 顾客等待空理发椅 理发师释放空理发椅 customer_ready 理发师等待,直到一个顾客坐 到理发椅 顾客坐到理发椅上,给理发师 发出信号 mutex 等待理发师空闲,执行理发或 收款操作 理发师执行理发或收款结束, 进入空闲状态 mutex1 执行入队或出队等待 入队或出队结束,释放信号 finished[i] 顾客等待对应编号理发师理 发结束 理发师理发结束,释放信号 leave_barberchair 理发师等待顾客离开理发椅 顾客付款完毕得到收据,离开 理发椅释放信号 payment 收银员等待顾客付款 顾客付款,发出信号 receipt 顾客等待收银员收、开具收据收银员收款结束、开具收据, 释放信号
伪码: semaphore stand_capacity=5; semaphore sofa=4; semaphore barber_chair=3; semaphore customer_ready=0; semaphore mutex=3; semaphore mutex1=1; semaphore finished[3]={0,0,0}; semaphore leave_barberchair=0; semaphore payment=0; semaphore receipt=0; void customer() { int barber_ wait(stand_capacity); //等待进入理发店 enter_room(); //进入理发店 wait(sofa); //等待沙发 leave_stand_section(); //离开站席区 }
桌上有一空盘,允许存放一只。爸爸可向盘中放,也可向盘中放,儿子专等吃盘中的桔子,女儿专等吃盘中的苹果。规定当盘空时一次只能放一只水果供吃者取用,请用P、V原语实现爸爸、儿子、女儿三个并发进程的同步。分析 在本题中,爸爸、儿子、女儿共用一个盘子,盘中一次只能放一个。当盘子为空时,爸爸可将一个水果放入果盘中。若放入果盘中的是,则允许儿子吃,女儿必须等待;若放入果盘中的是,则允许女儿吃,儿子必须等待。本题实际上是生产者-消费者问题的一种变形。这里,生产者放入缓冲区的产品有两类,消费者也有两类,每类消费者只消费其中固定的一类产品。
解:在本题中,应设置三个信号量S、So、Sa,信号量S表示盘子是否为空,其初值为l;信号量So表示盘中是否有,其初值为0;信号量Sa表示盘中是否有,其初值为0。同步描述如下: int S=1; int Sa=0; int So=0;
/*父亲进程*/
/*儿子进程*/
daughter();
/*女儿进程*/
将放入盘中;
if(放入的是)V(So);
从盘中取出;
daughter()
从盘中取出;
这么好帖子没人顶的
贴吧热议榜
使用签名档&&
保存至快速回贴哲学家就餐问题的分析与解决方案
1.进程互斥与同步,死锁基本知识
在多道程序环境下,进程有异步和同步两种并发执行方式。异步执行是指运行中的各进程在操作的调度下以不可预知的速度向前推进。异步执行的进程大多没有时序要求,不存在&执行结果与语句的特定执行顺序有关&的条件竞争。然而存在一类协作进程,&保证数据的一致性& 的前提要求它们必须按某种特定顺序执行,并且遵守如下两种限制。
(1)R1(顺序化执行):进程A 的eventA事件必须发生在进程B的eventB事件之前;
(2)R2(互斥执行):进程 A的eventA事件与进程B的eventB事件不能同时发生。把上述限制下多进程的运行状态叫作进程的同步执行。进程同步执行时因存在着明显的执行上的时序要求而相互等待。如果说进程异步是进程并发执行的自然结果,那么进程同步则需要程序员通过准确嵌入一些诸如加解锁来确保实现。
信号量无疑是一个较为理想的同步工具。它最早由荷兰科学家EdsgerDijkstra于1965年提出,该工具具有如下三个优点:(1)仅需要两个基本操作即可完成进程的同步和互斥,而且两个原子操作代码简洁高效, 易于扩充;(2) 精心设计的信号量对象类似一条条&触发器&规则,加上信号量机制的强制作用可以帮助程序员少犯错误;(3)信号量已在很多系统中实现,解决方案中有意识地选用信号量无疑将使进程更&瘦身&,运行更高效。信号量技术的引入是对早期忙等型(busywaiting)进程控制变量是个巨大的提升,但在使用过程中仍然存在不少缺点:一是不能随时读取信号量的值, 必要时须重复定义一个跟踪信号量值的普通变量,二是程序员对信号量的PV操作的正确使用与否没有任何控制和保证(后来引入管程和条件变量,PV操作完全由编译器而非 程序员安排),不合理地使用将导致进程饥饿甚至死锁。死锁应尽可能阻止,系统死锁导致诸进程将进入无法向前推进的僵持状态, 除非借助于外力。死锁的原因除了系统资源偏少之外,更多的是进程推进速度不当, 或者说进程申请和释放信号量的顺序不合理所致,毕竟系统提供的资源是有限的。以哲学家就餐问题为例,若派发给每位哲学家一双筷子(更准确地说,6支就足够), 则一定不会死锁。事实上,若信号量的PV操作顺序处置得当,5支筷子同样也可以保证不会发生死锁。
死锁是 《操作系统原理》课程中的1个很重要的概念, 它描述的是多个进程因竞争资源而造成的1种僵局 ,若无外力作用 ,这些进程将永远不能再向前推进。产生死锁的原因主要有2点: 1是竞争资源 ; 2是进程推进顺序不当。
2.哲学家就餐问题
哲学家就餐问题是在计算机科学中的一个经典问题,用来演示在并行计算中多线程同步(Synchronization)时产生的问题。在1971年,著名的计算机科学家艾兹格?迪科斯彻提出了一个同步问题,即假设有五台计算机都试图访问五份共享的磁带驱动器。稍后,这个问题被托尼?霍尔重新表述为哲学家就餐问题。这个问题可以用来解释死锁和资源耗尽。
哲学家就餐问题可以这样表述,假设有五位哲学家围坐在一张圆形餐桌旁,做以下两件事情之一:吃饭,或者思考。吃东西的时候,他们就停止思考,思考的时候也停止吃东西。餐桌中间有一大碗意大利面,每两个哲学家之间有一只餐叉。因为用一只餐叉很难吃到意大利面,所以假设哲学家必须用两只餐叉吃东西。他们只能使用自己左右手边的那两只餐叉。哲学家就餐问题有时也用米饭和筷子而不是意大利面和餐叉来描述,因为很明显,吃米饭必须用两根筷子。
哲学家从来不交谈,这就很危险,可能产生死锁,每个哲学家都拿着左手的餐叉,永远都在等右边的餐叉(或者相反)。即使没有死锁,也有可能发生资源耗尽。例如,假设规定当哲学家等待另一只餐叉超过五分钟后就放下自己手里的那一只餐叉,并且再等五分钟后进行下一次尝试。这个策略消除了死锁(系统总会进入到下一个状态),但仍然有可能发生&活锁&。如果五位哲学家在完全相同的时刻进入餐厅,并同时拿起左边的餐叉,那么这些哲学家就会等待五分钟,同时放下手中的餐叉,再等五分钟,又同时拿起这些餐叉。
在实际的计算机问题中,缺乏餐叉可以类比为缺乏共享资源。一种常用的计算机技术是资源加锁,用来保证在某个时刻,资源只能被一个程序或一段代码访问。当一个程序想要使用的资源已经被另一个程序锁定,它就等待资源解锁。当多个程序涉及到加锁的资源时,在某些情况下就有可能发生死锁。例如,某个程序需要访问两个文件,当两个这样的程序各锁了一个文件,那它们都在等待对方解锁另一个文件,而这永远不会发生。
3. 信号量机制解决哲学家就餐问题
当5个哲学家进程并发执行时,某个时刻恰好每个哲学家进程都执行申请筷子,并且成功申请到第i支筷子(相当于5个哲学家同时拿起他左边的筷子), 接着他们又都执行申请右边筷子, 申请第i+1支筷子。此时每个哲学家仅拿到一支筷子, 另外一支只得无限等待下去, 引起死锁。在给出几种有效阻止死锁的方案之前,首先给出两个断言:
(1)系统中有N个并发进程。 若规定每个进程需要申请2个某类资源, 则当系统提供N+1个同类资源时,无论采用何种方式申请资源, 一定不会发生死锁。分析:N+1个资源被N 个进程竞争, 由抽屉原理可知, 则至少存在一个进程获2个以上的同类资源。这就是前面提到的哲学家就餐问题中5个哲学家提供6支筷子时一定不会发生死锁的原因。
(2)系统中有N个并发进程。 若规定每个进程需要申请R个某类资源, 则当系统提供K=N*(R-1)+1个同类资源时,无论采用何种方式申请使用,一定不会发生死锁。分析:在最坏的情况下,每个进程都申请到R-1个同类资源, 此时它们均阻塞。 试想若系统再追加一个同类资源, 则 N 个进程中必有一个进程获得R个资源,死锁解除。
结合以上分析,哲学家就餐问题可以被抽象描述为:系统中有5个并发进程, 规定每个进程需要申请2个某类资源。 若系统提供5个该类资源, 在保证一定不会产生死锁的前提下,最多允许多少个进程并发执行?假设允许N个进程, 将R=2,K=5带入上述公式, 有N*(2-1)+1=5所以 N=4。也就意味着,如果在任何时刻系统最多允许4个进程并发执行, 则一定不会发生死锁。 大多数哲学家就餐问题死锁阻止算法都是基于这个结论。
增加一个信号量,控制最多有4个进程并发执行,算法如下:
Semaphorechopstick[5]={1,1,1,1,1};//分别表示5支筷子
Semaphorefootman=4;//初始值为4最多允许4个哲学家进程同时进行
Philosopher(inti)
{while(true)
{wait(footman);
Wait(chopstick[i]);//申请左筷子
Wait(chopstick[(i+1)%5]);//申请右筷子
Signal(chopstick[i]);//释放左筷子
Signal(chopstick[(i+1)%5]);//释放右筷子
Signal(footman);
4.基于退回机制的哲学家进餐问题的解决
回退机制的理论依据是处理死锁基本方法中的预防死锁策略。预防死锁是指通过设置某些限制条件 ,去破坏产生死锁的 4 个必要条件中的一个或几个来防止死锁的发生. 其中&摒弃不剥夺条件&规定,当一个进程提出新的资源请求而不能立即得到满足时 ,必须释放其已经保持了的所有资源 , 即已经占有的资源可以被剥夺。根据上面的理论 ,本文解决哲学家进餐问题的基本思路是 ,让每名哲学家先去申请他左手边的筷子 ,然后再申请他右手边的筷子 ,如果右手边的筷子不空闲, 则比较当前哲学家 i 和他右手边的哲学家( i +1)%5 ,看谁取得各自左手边筷子的时间更晚, 令其回退( 即释放左手筷子, 再重新申请左手筷子), 直到此哲学家右手边的筷子空闲为止。通过设置回退机制可以确保每位哲学家都能顺利进餐。
通过信号量来描述该算法 ,代码如下:
semaphore chopstick[ 0 &4] ={ 1 , 1 , 1 , 1 , 1};
/*chopstick [ ] :筷子信号量数组,初始值均为 1 ,表示开始时 5 根筷子都可用*/
philosopher ( i) // i : 哲学家编号, 从0到4
{ think( );//哲学家正在思考
wait( chopstick( i) );//取左侧的筷子
while (右手边筷子不空闲)
{ if (当前哲学家i比旁边哲学家( i +1)%5 晚拿到左手筷子) //%为取模运算
{哲学家i释放左手边的筷子;
think( );//哲学家i思考
哲学家i重新取左侧的筷子;
{哲学家( i +1)%5 释放左手边的筷子;
think( );//哲学家( i +1)%5 思考
哲学家( i +1)%5 重新取左侧的筷子;
wait( chopstick( ( i +1)%5) );//取右侧筷子
eat();//进餐
signal( chopstick( i) );//把左侧筷子放回原位
signal( chopstick( ( i +1)%5) );//把右侧筷子放回原位
5.用附加规则解决哲学家进餐问题
为了预防死锁的产生,我们添加一条竞争规则:所有哲学家先竞争奇数号筷子,获得后才能去竞争偶数号筷子(由于5号哲学家左右都是奇数号筷子,在本文中规定他先竞争5号筷子)。这样的话就总会有一名哲学家可以顺利获得两支筷子开始进餐。此方法的本质是通过附加的规则,让哲学家按照一定的顺序请求临界资源&&筷子。这样的话,在资源分配图中就不会出现环路,破坏了死锁生的必要条件之一:&环路等待&条件,从而有效地预防了死锁的产生。接下来我们用
语言来实现该刚才描述的策略。在实现代码中用五个线程表示五个哲学家的活动, 用一个逻辑型数组表示筷子的状态。 在此问题中,筷子是临界资源,必须互斥地进行访问。我们为筷子定义一个类,其中包含了表示筷子状态的逻辑。
class Chopsticks
/* 用 used[1]至 used[5]五个数组元素分别代表编号 1 至 5 的五支筷
子的状态 */
/* false 表示未被占用,true 表示已经被占用。 used[0]元素在程序中
private boolean used[]={true,false,false,false,false,false};
/* 拿起筷子的操作 */
public synchronized void takeChopstick()
/* 取得该线程的名称并转化为整型,用此整数来判断该哲学家应该用哪两支筷子 */
/* i 为左手边筷子编号,j 为右手边筷子编号 */
String name=Thread.currentThread().getName();
int i=Integer.parseInt(name);
/* 1~4 号哲学家使用的筷子编号是 i 和 i+1,5 号哲学家使用
的筷子编号是 5 和 1 */
int j=i==5?1:i+1;
/* 将两边筷子的编号按奇偶顺序赋给 odd,even 两个变量 */
if(i%2==0){even=i;odd=j;}
else {odd=i;even=j;}
/* 首先竞争奇数号筷子 */
while(used[odd])
try{wait();}
catch(InterruptedException e){}
used[odd]=
/* 然后竞争偶数号筷子 */
while(used[even])
try{wait();}
catch(InterruptedException e){}
used[even]=
}/*放下筷子的操作 */
public synchronized void putChopstick()
String name=Thread.currentThread().getName();
int i=Integer.parseInt(name);
int j=i==5?1:i+1;
/* 将相应筷子的标志置为 fasle 表示使用完毕, 并且通知其
他等待线程来竞争 */
notifyAll();
当某一哲学家线程执行取得筷子方法时, 程序会根据该线程的名称来确定该线程需要使用哪两支筷子,并且分辨出哪支筷子编号是奇数,按照先奇后偶的顺序来试图取得这两支筷子。 如果这两支筷子都未被使用(即对应的数组元素值为 false),该哲学家线程即可先后取得这两支筷子进餐,否则会在竞争某支筷子失
败后执行 wait()操作进入 Chopsticks 类实例的等待区, 直到其他的哲学家线程进餐完毕放下筷子时用 notifyAll()将其唤醒。当某一哲学家线程放下筷子时, 程序会将放下的筷子对应的数组元素值置为 false,并用 notifyAll()唤醒在等待区里的其他线程。
接下来定义出哲学家类
class Philosopher extends Thread
public Philosopher(String name,Chopsticks chopsticks)
/* 在构造实例时将 name 参数传给 Thread 的构造函数作为线程的名称 */
super(name);
/* 所有哲学家线程共享同一个筷子类的实例 */this.chopsticks=
public void run()
/* 交替地思考、拿起筷子、进餐、放下筷子 */
while(true)
thinking();
chopsticks.takeChopstick();
chopsticks.putChopstick();
public void thinking()
/* 显示字符串输出正在思考的哲学家,用线程休眠1秒钟来模拟思考时间 */
System.out.println (&Philosopher & +Thread.currentThread ().getName()+& is thinking.&);
try{Thread.sleep(1000);}
catch(InterruptedException e){}
public void eating()
/* 显示字符串输出正在进餐的哲学家,并用线程休眠 1 秒钟来模拟进餐时间 */
System.out.println (&Philosopher & +Thread.currentThread ().getName()+& is eating.&);
try{Thread.sleep(1000);}
catch(InterruptedException e){}
在运行时,用Philosopher 类产生五个线程模拟五个哲学家,每个线程不停地重复执行思考、拿起筷子、进餐、放下筷子的过程。 线程的名称依次为&1&,
&2&,&3&,&4&,&5&(字符串类型)
主程序如下
public class Mainz
public static void main(String[] args)
/* 产生筷子类的实例 chopsticks */
Chopsticks chopsticks=new Chopsticks();
/* 用筷子类的实例作为参数, 产生五个哲学家线程并启动*/
/* 五个哲学家线程的名称为 1~5 */
new Philosopher(&1&,chopsticks).start();
new Philosopher(&2&,chopsticks).start();
new Philosopher(&3&,chopsticks).start();
new Philosopher(&4&,chopsticks).start();
new Philosopher(&5&,chopsticks).start();
运行后,从输出的结果可以看到五个哲学家线程交替地进行思考和进餐,互斥地使用筷子,有效地避免了死锁的发生。
本文对哲学家进餐问题产生死锁的现象进行了分析,提出了3种解决方案, 并从在理论依据、算法设计、实现等方面进行了较为详细地阐述。这对学习和理解《操作系统原理》课程中的经典进程同步问题有一定的参考价值。
(window.slotbydup=window.slotbydup || []).push({
id: '2467140',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467141',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467142',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467143',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467148',
container: s,
size: '1000,90',
display: 'inlay-fix'

我要回帖

更多关于 ps整张图片改变尺寸 的文章

 

随机推荐