进程同步早期解决方案——软件方法篇

首先说明同步机制遵循的原则:

空闲让进无进程处于临界区时,请求进入临界区的进程可立即进入

忙则等待有进程处于临界区时,请求进入临界区的进程必须等待

有限等待:要访问临界资源的进程,须保证在有限时间内可进入临界区。

让权等待:当进程不可进入临界区时,应释放处理机

 

接着来看进程同步的早期方案:

(一)软件解法1——轮询

(1)基本思想:

设置轮转标志turn,即设置一个变量,等于当前可以访问临界区的进程编号。初始时turn等于某进程的标号,初始时设置turn=i,表示初始时访问权在i手里。其次在每个进程的进入区里,判断turn是否是本进程标号,不是,则空转等待。在退出区里将turn赋值给其他进程的标号。这样轮流访问。

·i进程代码如下:

进入区:while(turn!=i)  ;

临界区:XXXX

退出区:turn=j;

(2)违背原则:

让权等待:不可访问临界区的进程在进入区里一直检查,空转等待

空闲让进:由于严格限制资源访问顺序,初始设置的可访问临界区的进程不一定会访问临界区,而处理机交给其他进程时,改进程可能正好需要访问临界区,但由于初始的进程还未访问或者不需要访问临界区。所以该进程仍然不让进入临界区。

 

(二)软件解法2——按需访问

(1)基本思想:

设置资源空闲标志busy(全局变量),即设置一个二值变量,表示临界区当前是否可以访问。初始时busy等于false,表示没有进程访问临界区,当前可访问。其次在每个进程的进入区,判断busy是否是false,是则表示不忙,可以进入,若是true,表示忙需要等待。当busy为false判断成功后,先将bust置为true,再进入临界区。在退出区里,将busy置为false。

·i进程代码如下:

进入区:while(busy)  ;

               busy=ture;

临界区:XXXX

退出区:busy=false;

(2)违背原则:

让权等待:不可访问临界区的进程在进入区里一直检查,空转等待

忙则等待:有这么一种情况。当临界区资源被进程释放后,进程A此时顺利通过检查循环,正准备设置busy为true之后进入临界区时,还没设置,就切换到进程B了,此时,由于A尚未设置busy为true,故B也可以顺利通过检查和循环。之后的情况就是二者同时访问临界区,未满足忙则等待。

 

(三)软件解法3——访前先看

(1)基本思想

为每个进程设置一个欲访问标志。该方法当某个进程想要访问临界区,在进入区的检查和循环环节之前,提前设置该进程的欲访问标志为desire,表示本进程现在想要访问临界区。而进入区的检查是检查此时其他进程是否有想要访问临界区的(其欲访问标志为true),有,则循环等待。若没有,则本进程直接访问临界区。在退出区里,要设置本进程的欲访问标志为false。

·i进程代码如下:

进入区:i_desire=true;

              While(j_desire=true)  ;

临界区:XXXX

退出区:i_desire=false;

注意,该方法相当于按需访问的改进版,把busy放到进入区之前,防止再次发生未设置busy就发生了进程切换的情况(这样会导致发生违背忙则等待原则的情况)。该方案主要解决了按需访问违背忙则等待原则的问题,因为忙却不等待,一起访问临界区,后果是很严重的。

(2)违背原则:

让权等待:不可访问临界区的进程依然在进入区里一直检查,空转等待

空闲让进:有这么一种情况。当进程A设置完A_desire等于true时,表明了想访问临界区的意图,就在此时,发生调度,切换到进程B,这时B也想访问临界区,设置了B_desire等于true。在这种情况下,每个进程的欲访问标志都为true,所以每个进程都会卡在进入区的检查循环环节,并且所有进程都在一直空转等待。进入区此时是空闲的,但没有进程访问。

有限等待:在“②”的情况下,所有进程都卡在了进入区,无法进入。大家都会一直空转等待下去,所以违背了有限等待原则。

 

(四)软件解法4——Peterson算法

(1)基本思想

将软件解法1轮询和软件解法3访前先看结合不仅设置turn来规定当前大家里面谁有临界区的访问权还为每个进程设置欲访问标志x_desire。每个进程在进入区的时候,设置x_desire为true,表明自己真的很想访问临界区。接着,设置turn等于其他进程。在退出区里,设置欲访问标志为false,表明自己已经访问完了,不想访问了。

·i进程代码如下:

进入区:i_desire=ture, turn=j;

              While(j_desire=true && turn=j)  ;

临界区:XXXX

退出区:i_desire=false;

注意:初始情况下,不设置turn的值,turn的值由每个进程自己在进入区里面设置,但是,每个进程设置turn的时候,不是设置成自己,而是设置成别人。这样做的目的是,如果每个进程都把turn设置成自己,然后自己又把自己的desire置为true,那么在检查是否可以访问临界区的时候,大家各执一词,都想进入临界区,引发各种混乱。相反,在进入区里面,先声明自己想访问临界区,即把x_desire置为true,接着再主动把访问权礼让给别人,即把turn设置成别人。这样的话,每个人都表明自己的想法,然后又礼让访问权,就不会发生冲突。再者,在判断的时候,等待的条件是(两个),另一个人不仅有访问临界区的欲望而且现在控制权在他手中,如果其中一个条件不满足(你想访问但控制权在我手里,或者是你压根不想访问临界区),那么本进程会突破循环,直接开始访问临界区。

一般进程X到达了检查与循环的语句的时候,该进程必定是想访问临界区的,因为之前已经声明过x_desire=true了。在检查和循环之前,如果发生了切换,那么其他进程会把控制权给X进程,那么该X就可以突破检查,直接开始访问。如果没有发生切换,而其他进程在之前已经声明了想要访问,但还没访问。这时候X在检查语句中,其他进程有欲望且有控制权的条件就成立了,X就需要等待。(这一系列过程可以换位思考其他进程的情况,大家都是这么个情况)

一旦发生了X突破检查,进入临界区的时候,此时,必然有这么个事实存在,即其他进程没有欲望,或者其他进程没有权限(或二者兼备)。那么伴随着整个X访问临界区的时光里访问权会一直X手中的(并且此时X的欲望明确是置为true的),为什么,因为就算发生了进程切换,其他进程在检查语句里,也会卡住。也就是说,当某进程成功开始访问临界区的时候,其他进程是明明白白被卡住的。

总结一下就是,在某一时刻,即使人人都有欲望,但是turn的值是确定的,只能允许一个人访问,无论期间是否再次发生调度,其他进程都是卡在检查的地方。

PS:另一种实现方式

(图片侵删)

该方式同理,先自己设置让turn=process,让自己卡住,接着发生调度,控制权给了别的进程,别的进程重新设置process,别人会把别人自己卡住。待会儿切换回来,原来的进程就不会卡在检查语句里,正好执行了。

(2)违背原则:

让权等待:依然是不停的空转等待。

 

总的来看,软件解法都很难解决让权等待,每个解法都是在进入区里检查临界区的可用性,在时间片内不停地检查检查检查检查检查……从而造成了一种不必要的浪费。

  • 11
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值