15-互斥的软件实现方法
互斥的软件实现方法
单标志法
算法思想
两个进程在访问完临界区后会把使用临界区的权限转交给另一个进程,也就是说每个进程进入临界区的权限只能被另一个进程赋予。
代码示例
int turn =0; //turn 表示当前允许进入临界区的进程号
P0代码
P0进程:
while(turn != 0); ①
critical section; ②
turn = 1; ③
remainder section;④
P1代码
while(turn !=1); ⑤
critical section; ⑥
turn = 0; ⑦
remainder section;⑧
工作流程
turn的初值为0,即刚开始只允许0号进程进入临界区。
若P1先上处理机运行,则会一直卡在 ⑤。直到P1的时间片用完,发生调度,切换P0上处理机运行。
代码①不会卡住P0,P0 可以正常访问临界区,在PO访问临界区期间即时切换回P1,P1依然会卡在⑤。
只有P0在退出区将0设置为1后,P1c才能进入临界区。
算法限制
这种"轮流访问"带来的问题是,如果此时允许进入临界区的进程是P0,而P0一直不能访问临界区,那么虽然此时临界区空闲,但是并不允许P1访问,违背了空闲让进原则。
双标志先检查法
算法思想
设置一个布尔型数组flag[],数组中的各个元素用来标记各个进程想进入临界区的意愿,比如flag[0]=true意味着0号进程想要进入临界区。每个进程在进入临界区前先检查当前有没有别的进程想进入临界区,如果没有,则把自身对应的标志设为true,之后访问临界区。
代码示例
初始代码
bool flag[2]; //表示进入临界区意愿的数组
flag[0]=false;
flag[1]=false;//刚开始设置为两个进程都不想进入临界区
P0代码
while(flag[1]); ①
flag[0]=true; ②
critical section; ③
flag[0]=false; ④
remainder section;
P1代码
while(flag[0]); ⑤//如果此时P0想要进入临界区,P1就一直循环等待
flag[1]=true; ⑥//标记为P1进程想要进入临界区
critical section;⑦//访问临界区
flag[1]=false; ⑧//访问完临界区,修改标志为P1不想使用临界区
remainder section;
如果按照①⑤②⑥③⑦的顺序执行,P0和P1会同时访问临界区。
算法限制
因为进入区的检查和上锁两个处理不是一气呵成的。检查后,上锁前可发生进程切换,导致两个进程会同时访问临界区,违反"忙则等待"原则。
双标志后检查法
双标志先检查的改版,前一个算法是先检查,后上锁,但是两个操作又无法一气呵成,因此导致了两个进程同时进入临界区的问题。因此,人们又想到了先上锁后检查的方法,来避免上述问题。
代码示例
初始代码
bool flag[2]; //表示进入临界区意愿的数组
flag[0]=false;
flag[1]=false;//刚开始设置为两个进程都不想进入临界区
P0进程
flag[0]=true; ①
while(flag[1]);②
critical section;③
flag[0] =false;④
remainder section;
P1进程
flag[1]=true;⑤
while(flag[0]);⑥
critcial section;⑦
flag[0] =false;⑧
remainder section;
若按照①⑤②⑥的顺序执行,P0和P1都将无法进入临界区。
算法限制
双标志法虽然解决了**"忙则等待"的问题,但是又违背了空闲让进和有限等待原则**,因此各个进程长期无法访问临界资源会产生“饥饿”现象。
Peterson 算法
算法思路
双标志后检查法中,两个进程都争着想进入临界区,但是谁也不让谁,最后谁都无法进入临界区。Gary L Peterson想到了一种方法,如果双方都想着进入临界区,可以让进程采用孔融让梨,主动让对方先使用临界区。
代码示例
初始代码
bool flag[2]; //表示进入临界区意愿的数组,初始值都是false
int turn=0; //turn 表示优先让哪个进程进入临界区
P0进程
flag[0]=true; ①
turn =1; ②
while(flag[1]&&turn==1); ③
critical section;④
flag[0]=false;⑤
remainder section;
P1进程
flag[1]=true; ⑥ //表示自己想进入临界区
turn=0; ⑦ //可以优先让对方进入临界区
while(flag[0]&&turn==0);⑧//对方相近,且最后一次是自己让梨,那自己就循环等待
critical section; ⑨
flag[1]=false; ⑩
remainder section;
算法限制
Peterson算法用软件方法解决了进程互斥问题,遵循了空闲让进、忙则等待、有限等待,但是没有设置一些阻塞队列,没有遵循让权等待方法,仍然会发生忙等,Peterson方法是四种方法里最好的。