軟件實現方法
在進入區設置和檢查一些標志來標明是否有進程在臨界區中,如果已有進程在臨界區,則在進入區通過循環檢查進行等待,進程離開臨界區后則在退出區修改標志。
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解決“飢餓”現象。