实现临界区互斥的基本方法
软件实现方法
在进入区设置和检查一些标志来标明是否有进程在临界区中,如果已有进程在临界区,则在进入区通过循环检查进行等待,进程离开临界区后则在退出区修改标志。
1) 算法一:单标志法。
该算法设置一个公用整型变量turn,用于指示被允许进入临界区的进程编号,即若turn=0,则允许P0进程进入临界区。该算法可确保每次只允许一个进程进入临界区。
- // 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[j] = FALSE; // 退出区
- remainder section; // 剩余区
优点:不用交替进入,可连续使用;缺点:Pi和Pj可能同时进入临界区。按序列①②③④ 执行时,会同时进入临界区(违背“忙则等待”)。即在检查对方flag之后和切换自己flag之前有一段时间,结果都检查通过。这里的问题出在检查和修改操作不能一次进行。
3) 算法三:双标志法后检查。
算法二是先检测对方进程状态标志后,再置自己标志,由于在检测和放置中可插入另一个进程到达时的检测操作,会造成两个进程在分别检测后,同时进入临界区。为此,算法三釆用先设置自己标志为TRUE后,再检测对方状态标志,若对方标志为TURE,则进程等待;否则进入临界区。
- // Pi进程
- flag[i] =TRUE;
- while(flag[j]);
- critical section;
- flag[i] =FLASE;
- remainder section;
- // Pj进程
- flag[j] =TRUE; // 进入区
- while(flag[i]); // 进入区
- critical section; // 临界区
- flag [j] =FLASE; // 退出区
- remainder section; // 剩余区
当两个进程几乎同时都想进入临界区时,它们分别将自己的标志值flag设置为TRUE,并且同时检测对方的状态(执行while语句),发现对方也要进入临界区,于是双方互相谦让,结果谁也进不了临界区,从而导致“饥饿”现象。
4)算法四:Peterson’s Algorithm。
为了防止两个进程为进入临界区而无限期等待,又设置变量turn,指示不允许进入临界区的进程编号,每个进程在先设置自己标志后再设置turn 标志,不允许另一个进程进入。这时,再同时检测另一个进程状态标志和不允许进入标志,这样可以保证当两个进程同时要求进入临界区,只允许一个进程进入临界区。
- // Pi进程
- flag[i]=TURE; turn=j;
- while(flag[j]&&turn==j);
- critical section;
- flag[i]=FLASE;
- remainder section;
- // Pj进程
- flag[j] =TRUE;turn=i; // 进入区
- while(flag[i]&&turn==i); // 进入区
- critical section; // 临界区
- flag[j]=FLASE; // 退出区
- remainder section; // 剩余区
本算法的基本思想是算法一和算法三的结合。利用flag解决临界资源的互斥访问,而利用turn解决“饥饿”现象。