实现临界区互斥的基本方法

----------软件实现方法:

               在进入区设置和检查一些标志来表明是否有进程在临界区中,如果已有进程在临界区,则在进入区通过循环检查进行等待,进程离开临界区后则在退出区修改

          标志。

               (1)、算法一:单标志法。(违背“空闲让进”原则)

                         该算法设置一个公用整型变量 turn ,用于指示被允许进入临界区的进程编号,即,若turn = 0 ,则允许p0 进程进入临界区。该算法可确保每次只允许一个

                     进程进入临界区。但两个进程必须交换进入临界区,如果某个进程不再进入临界区了,那么另一个进程也将无法进入临界区(违背“空闲让进”)。这样很容易

                     造成资源利用不充分。

                           假如,p0顺利进入临界区并从临界区离开,那么此时临界区是空闲的,但p1 并没有进入临界区的打算,turn = 1 一直成立,p0 就无法再次进入临界区了

                     (一直被 while 死循环困住)

                           p0 进程:

                                while(turn != 0);          //进入区

                               critical section  ;          //临界区

                                turn = 1;                       //退出区

                                remainder section;   //剩余区

                             p1进程:

                                 while(turn != 1);           //进入区

                                 critical section;            //临界区

                                  turn = 0;                       //退出区

                                  remainder section;   //剩余区

                  (2)、算法二:双标志法先检查。(违背“忙则等待”原则)

                                    该算法的基本思想是在每一个进程访问临界区资源之前,先查看一下临界区资源是否正被访问,若正被访问,该进程需等待;否则,进程才进入自己

                            自己的临界区。为此,设置一个数据  flag[ i ] ,如第i个元素值为 FALSE ,表示Pi进程未进入临界区,值为 TRUE ,表示Pi进程进入临界区。

                            Pi 进程:

                                    while(flag[ j ]);             //进入区

                                    flag[ i ] = TRUE;          //进入区

                                    critical section;           //临界区

                                    flag[ i ] = FALSE;        //退出区

                                    remainder section;   //剩余区

                            Pj进程:

                                     while(flag[ i ]);            //进入区

                                     flag[ j ] = TRUE;         //进入区

                                     critical section;          //临界区

                                     flag[ i ] = FALSE;        //退出区

                                     remainder section;   //剩余区

                            优点:不用交替进入,可连续使用。

                            缺点:Pi 进程和 Pj进程可能同时进入临界区。

                                        检查和修改操作不能一次进行。

                (3)、算法三:双标志法后检查(会导致“饥饿”现象)

                                   算法二是先检查对方进程状态标志后,再置自己的标志,由于在检查和放置中可插入另一个进程到达时的检测操作,会造成两个进程在分别检查

                            后,同时进入临界区。为此,算法三采用先设置自己标志为  TRUE  后,再检测对方状态标志,若对方标志位 TRUE,则进程等待;否则进入临界区。

                                  Pi进程:

                                  flag[ i ] =TRUE;               //进入区

                                  while(flag[ j ]);                 //进入区

                                  critical section;               //临界区

                                  remainder section;        //剩余区

                                  Pj进程:

                                  flag[ j ] =TRUE;                //进入区

                                  while(flag[ i ] );                 //进入区

                                  critical section;                //临界区

                                  remainder section;         //剩余区

                            当两个进程几乎同时都想进入临界区时,它们分别将自己的标志值 flag 设置为  TRUE ,并且同时检测对方的状态(执行 while 语句),发现对方

                       也要进入临界区,于是双方互相谦让,结果谁也进不了临界区,从而导致“饥饿”现象。

                    (4)、算法四:Peterson's Algorithm(皮特森算法:单标志法和双标志法后检查的结合)

                                为了防止两个进程为进入临界区而无限期等待,又设置变量 turn ,,每个进程在设置自己标志后再设置 turn 标志。这时,再同时检测另一个进程

                       状态标志不允许进入标志,这样可以保证当进程同时要求进入临界区,只允许一个进程进入临界区。  

                                Pi 进程:

                                flag[ i ] = TRUE; turn = j;             //进入区

                                while(flag[ j ] && turn == j);        //进入区

                                critical section;                            //l临界区

                                flag[ i ] = FALSE ;                         //退出区

                                 remainder section;                    //剩余区

                                Pj 进程:

                                flag[ j ] = TRUE; turn = i;             //进入区 

                                while(flag[ i ] && turn == i);        //进入区

                                critical section;                             //临界区

                                 flag[ j ] = FALSE;                         //退出区

                                 remainder section;                     //剩余区

                             具体如下:考虑进程  Pi ,一旦它设置 flag[ i ] = TRUE ,表示它想要进入临界区,同时 turn = j ,此时如果进程 Pj 已经在临界区中,则符合进程Pi 的while

                       循环条件,则Pi 不能进入临界区。而如果 Pj 进程没要进入临界区,即  flag[ j ] = FALSE ,循环条件不符合,则  Pi 进程可以顺利进入,反之亦然,本算法

                       的基本思想是:算法一和算法三的结合。利用 flag 解决临界资源的互斥访问,而利用  turn 解决“饥饿”现象。

----------硬件实现方法:

                       计算机提供了特殊的硬件指令,允许对一个字中的内容进行检测和修正,或者是对两个字的内容进行交换等。通过硬件支持实现临界区问题的低级方法或

                     称为 元方法

                   (1)、中断屏蔽方法:

                                  当一个进程正在使用处理机执行它的临界区代码时,要防止其他进程再进入其临界区访问的最简单的方法是:禁止一切中断发生,或称之为屏蔽中断、

                         关中断。

                                  因为CPU 只在发生中断时引起进程切换,这样屏蔽中断就能保证当前运行进程将临界区代码顺利地执行完,从而保证互斥的正确实现,然后再执行开

                          中断。其典型模式为:

                                  ....

                                  关中断;

                                  临界区;

                                  开中断;

                                  .....

                          这种方法限制了处理机交替执行的能力,因此执行的效率将会明显降低。对内核来说,当它执行更新变量或列表的几条指令期间关中断是很方便的,但是

                     将关中断的权利交给用户则很不明智,若一个进程关中断之后不再开中断,则系统可能会因此终止。

                    (2)、硬件指令方法:设立原子操作指令

                                TestAndSet 指令:这条指令是原子操作,即执行该代码时不允许被中断。其功能是:读出指定标志后把该标志设置为真。指令功能的描述如下:

                                 boolean TestAndSet(boolean *lock){

                                                boolean old;

                                                old = *lock;

                                                *lock = true;

                                                return old; 

                                 }

                              可以为每个临界资源设置一个共享布尔变量  lock ,表示资源的两种状态:true 表示正被占用,初值为  false 。在进程访问临界资源之前,利用

                        TestAndSet 检查和修改标志 lock ;若有进程在临界区,则重复检查,直到进程退出。利用该指令实现进程互斥的算法描述如下:

                               while TestAndSet(&lock);

                               进程的临界区代码段;

                               lock =  false;

                               进程的其他代码;

                               Swap  指令该指令的功能是交换两个字(字节)的内容。其功能描述如下:

                                Swap(boolean *a , boolean *b){

                                        boolean temp;

                                        temp = *a;

                                        *a = *b;

                                        *b = temp;

                                }

                               应为每个临界资源设置一个共享布尔变量 lock ,初值为   false;在每个进程中再设置一个局部布尔变量 key ,用于与 lock 变换信息。在进入临界区之前

                          先利用 Swap 指令交换 lock 与 key 的内容,然后检查 key 的状态;有进程在临界区时,重复交换和检查过程,直到进程退出。利用Swap 指令实现进程互斥的

                         算法描述如下:

                               key = true;

                               while(key != false);

                               Swap(&lock , &key);

                               进程的临界区代码段;

                               lock = false;

                               进程的其他代码;

                              硬件方法的优点:适用于任意数目的进程,不管是单处理机还是多处理机;简单、容易验证其正确性。可以支持进程内有多个临界区,只需为每个临界区

                         设立一个布尔变量。

                              硬件方法的缺点:进程等待进入临界区时要耗费处理时间,不能实现让权等待。从等待进程中随机选择一个进入临界区,有进程可能一直选不上,从而

                          导致“饥饿”现象。

                              注意:以上对  TestAndSet  和 Swap 指令的描述仅仅是功能实现,并非软件实现定义,事实上它们是由硬件逻辑直接实现的,不会被中断。

                              补充:以上的代码实现与我们平时在编译器上写的代码意义不同,以上的代码实现是为了表述进程实现同步和互斥的过程,并不是说计算机内部实现

                                           同步互斥就是这些代码。

----------信号量:利用PV 操作实现互斥

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小达人Fighting

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值