日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

【操作系统】互斥:软件解决方法

發布時間:2023/12/1 windows 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【操作系统】互斥:软件解决方法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

互斥:軟件解決方法

算法一

算法思路

預留一個全局內存區域,并標記為turn。進程(P0或P1)想進入它的臨界區執行時,要先檢查turn的內容。若turn的值等于進程號,則該進程可以進入它的臨界區;否則該進程被強制等待。等待進程重復地讀取turn的值。直到被允許進入臨界區。這一過程稱為忙等待(busy waiting)自旋等待(spin waiting),進程在獲得臨界區的訪問權并完成訪問后,必須為另一個進程更新turn的值。

P0 :

while(turn != 0) {/* busy waiting */} /* critical section */ turn = 1;

P1 :

while(turn != 1) {/* busy waiting */} /* critical section */ turn = 0;

缺陷

  • 進程必須嚴格交替(P0臨界區執行完后才會更新turn值,使得P1跳出忙等待狀態,同理P0也需等待P1臨界區執行完)使用它們的臨界區,因此執行的步調由兩個進程較慢的進程決定。
    例如:若P0在1小時內僅使用臨界區1次,而P1要以1000次/小時的速率使用臨界區,則P1就必須適應P0的節奏。
  • BUG

  • 若一個進程終止,則另一個進程就會被永久阻塞。無論進程是在臨界區內終止還是在臨界區之外終止,都會發生這種情況。
    例如:P0在執行到第二行代碼(臨界區內)時終止,此時turn值為0且此后不會被更新,因此P1將永久處于忙等待狀態;P0在執行到第三行代碼(臨界區外)時終止,此時turn值為1,于是P1進入臨界區,執行完后便將turn值置為0,而P0進程因為終止便不會再更新turn值,因此P1將永久處于忙等待狀態。
  • 算法二

    算法一僅由一個共享的仲裁變量去實現進程間的互斥,因此進程之間必須嚴格交替執行,進程之間的依賴關系過強

    算法二為每一個進程都配備了專門的”鑰匙“,這里定義一個bool數組flag,flag[0]與P0關聯,flag[1]與P1關聯,每個進程可檢查但不能改變另一個進程的flag值

    算法思路

    一個進程要進入臨界區時,它會周期性地檢查另一個進程的flag,直到其值為false,這表明另一個進程不在臨界區內。檢查進程立即設置自己的flag為true,進入自己的臨界區。離開臨界區時,將自己的flag設置為false。

    P0 :

    while(flag[1]) {/* busy waiting */} flag[0] = true; /* critical section */ flag[0] = false;

    P1 :

    while(flag[0]) {/* busy waiting */} flag[1] = true; /* critical section */ flag[1] = false;

    進步

  • 若一個進程在臨界區外終止,包括設置flag代碼時,則另一個進程不會被阻塞。
    例如:當P1在執行完第4行代碼后終止,此后flag[1]將一直保持false,因此P0將永遠不會進入忙等待狀態即說明其不會被阻塞
  • BUG

  • 若一個進程在臨界區內,或在進入臨界區之前已將flag設置為true時終止,則另一個進程就會永久阻塞
  • 沒有保證互斥!!
    例如:P1執行完第4行代碼后,于是P0跳出忙等待狀態,但P0還未來得及執行第二行代碼(將flag[0]設置為true)P1便又進入了臨界區,隨后P0也進入臨界區,便產生了訪問沖突
  • 下面采用Java多線程編程模擬算法二并驗證BUG-2

    package TEST;public class Multithreading {public static void main(String[] args) {Process p0 = new Process("P0", 0, 0);Process p1 = new Process("P1", 1, 1);p0.start();p1.start();} } class Process extends Thread {private static int var;private int var_right;private static boolean[] flag = new boolean[2];private String name;private int cnt_test = 100;private int No;private int No_other;public Process(String name, int No, int var_right) {super();this.name = name;this.No = No;this.var_right = var_right;this.No_other = (No + 1) % 2;}public void run() {for(int i = 0; i < cnt_test; i++) {while(flag[No_other]) { /* busy waiting */ }flag[No] = true;/*--- critical section begin---*/var = var_right;System.out.println(this.name + ":" + (var == var_right? var : "##"));/*--- critical section end---*/flag[No] = false;}} }

    兩個線程任務是,將公共變量var賦值為本線程對應正確的值var_right,并輸出當前var的值,若兩個線程保證互斥則var總是等于var_right(Condition ‘var == var_right’ is always ‘true’)即不會輸出##

    運行結果如下:

    P0:0 P1:## P0:0 P1:1 P0:0 P1:## P0:0 P1:## P0:0 P0:0 P0:0 P1:## P1:## P0:0 P1:1 P1:1 P0:## P1:1 P1:1 P1:1 P0:## P0:## P1:1 P0:0 P1:1 P1:## P0:0 P1:## P0:0 P1:1 P1:## P0:0 P1:1 P0:## P1:1 P0:## P1:1 P1:## P0:0 P0:0 P1:## P0:0 P1:1 P1:## P0:0 P0:0 P1:## P0:0 P1:1 P1:## P0:0 P1:## P0:0 P1:1 P1:## P0:0 P1:## P0:0 P1:1 P0:0 P1:1 P1:## P0:0 P0:0 P0:0 P0:0 P0:0 P0:0 P0:0 P0:0 P0:0 P0:0 P0:0 P0:0 P1:1 P0:0 P1:1 P0:0 P0:0 P1:1 P1:1 P1:1 P0:0 P1:## P1:1 P1:1 P1:1 P1:1 P1:1 P1:1 P1:1 P1:1 P1:1 P1:1 P1:1 P1:1 P1:1 P1:1 P1:## P0:0 P1:1 P1:## P0:0 P1:1 P1:## P0:0 P1:1 P1:## P0:0 P1:1 P1:1 P1:## P0:0 P1:1 P1:1 P0:0 P1:## P1:1 P1:1 P1:1 P1:1 P1:1 P1:1 P1:1 P1:1 P1:1 P1:1 P1:1 P1:1 P1:1 P1:1 P1:1 P1:## P0:0 P0:0 P0:0 P0:0 P0:0 P0:0 P0:0 P0:0 P0:0 P0:0 P0:0 P0:0 P0:0 P0:0 P0:0 P0:0 P0:0 P0:0 P0:0 P0:0 P0:0 P0:0 P0:0 P0:0 P0:0 P0:0 P1:1 P0:## P1:1 P1:1 P1:1 P1:1 P1:1 P1:1 P1:1 P1:1 P1:1 P1:1 P1:1 P1:## P0:0 P1:1 P1:## P0:0 P1:1 P1:1 P0:0 P0:0 P0:0 P0:0 P0:0 P0:0 P0:0 P0:0 P0:0 P0:0 P0:0 P0:0 P0:0 P0:0 P0:0 P0:0 P0:0 P0:0 P0:0 P0:0 P0:0Process finished with exit code 0

    可見采用算法二兩個線程之間發生了不少次的訪問沖突(輸出##)

    算法三

    算法二由于執行速率不匹配的原因,導致兩個進程同時處在臨界區的位置,所以算法二的方案失敗

    算法三通過簡單地交換兩條語句來解決這一問題

    算法思路

    將控制其他進程持續忙等待的語句提到了檢查flag值之前,確保了同一時刻只有一個進程進入臨界區

    P0 :

    flag[0] = true; while(flag[1]) {/* busy waiting */} /* critical section */ flag[0] = false;

    P1 :

    flag[1] = true; while(flag[0]) {/* busy waiting */} /* critical section */ flag[1] = false;

    進步

  • 解決算法二造成的訪問沖突問題,確保了互斥性
  • BUG

  • 算法二一樣,某一進程在臨界區內或在設置flag為true時終止,會引起其他進程永久阻塞
  • 若每個進程在執行while語句前都將flag設置為true,則每個進程都會認為另一個進程已經進入臨界區,進而引發死鎖
    例如:P0執行完第一行代碼后還未來得及執行while語句,P1也執行完了第一行代碼,此時flag[0]與flag[1]的值都為true,因此兩個進程都無法跳出忙等待的狀態,從而造成死鎖
  • 下面采用Java多線程編程模擬算法三并驗證BUG-2

    package TEST;public class Multithreading {public static void main(String[] args) {Process p0 = new Process("P0", 0, 0);Process p1 = new Process("P1", 1, 1);p0.start();p1.start();} } class Process extends Thread {private static int cnt_busy_wait = 0;private static int var;private int var_right;private static boolean[] flag = new boolean[2];private String name;private int cnt_test = 100;private int No;private int No_other;public Process(String name, int No, int var_right) {super();this.name = name;this.No = No;this.var_right = var_right;this.No_other = (No + 1) % 2;}public void run() {for(int i = 0; i < cnt_test; i++) {flag[No] = true;while(flag[No_other]) {/* busy waiting */System.out.println(this.name + " BusyWaiting: " + (++cnt_busy_wait));if(cnt_busy_wait > 999) return;}/*--- critical section begin---*/var = var_right;System.out.println(this.name + ":" + (var == var_right? var : "##"));/*--- critical section end---*/flag[No] = false;}} }

    運行結果如下:

    P0:0 P1 BusyWaiting: 1 P1 BusyWaiting: 3 P1 BusyWaiting: 4 P1 BusyWaiting: 5 P0 BusyWaiting: 2 P0 BusyWaiting: 7 P0 BusyWaiting: 8 P0 BusyWaiting: 9 P0 BusyWaiting: 10 P1 BusyWaiting: 6 P1 BusyWaiting: 12 P1 BusyWaiting: 13 P0 BusyWaiting: 11... ...P1 BusyWaiting: 995 P1 BusyWaiting: 996 P1 BusyWaiting: 997 P1 BusyWaiting: 998 P1 BusyWaiting: 999 P1 BusyWaiting: 1000 P0 BusyWaiting: 967Process finished with exit code 0

    可見結果只被正確輸出了一次,此后兩線程皆處在忙等待狀態,形成死鎖

    算法四

    算法三中,一個進程在設置其狀態時是不知道另一個進程的狀態的。由于每一個進程堅持要進入臨界區,導致死鎖發生

    算法四在算法三的基礎上引入**“謙讓”**的機制,在忙等待中隨時重設flag,一定程度上避免了死鎖發生

    算法思路

    當出現死鎖情況時(兩者都進入忙等待狀態),P0進程將flag[0]置為false并在該狀態延遲1秒,P1便可在這1秒之內跳出忙等待狀態,從而避免了死鎖的情況

    P0 :

    flag[0] = true; while(flag[1]) {flag[0] = false;delay(1); // dalay 1 secflag[0] = true; } /* critical section */ flag[0] = false;

    P1 :

    flag[1] = true; while(flag[0]) {flag[1] = false;delay(1); // dalay 1 secflag[1] = true; } /* critical section */ flag[1] = false;

    進步

  • 一定程度的避免了死鎖的出現
  • 缺陷

  • 當兩個進程自上而下的語句幾乎同時被執行時,則兩者都不會進入臨界區。嚴格來說,這不是死鎖,因為兩個進程執行速率的相對變化會打破這種狀況,允許其中一個進程進入臨界區,這種狀態稱為活鎖(livelock)(盡管該場景不會維持很長時間,但仍然是一種有可能發生的情形)
  • Dekker 算法

    算法四可能會出現 “互相謙讓” 的情況

    Dekker算法通過turn變量表示哪個進程有權進入它的臨界區,避免了**“互相謙讓”**的情況

    算法思路

    當P0要進入它的臨界區時,將其flag設置為true,然后檢查P1的flag。若為false,P0可以立即進入它的臨界區;否則,P0要檢查turn,若發現turn為0,則P0要持續周期性地檢查P1的flag。而P1需要延期執行并將flag設置為false,讓P0執行。P0完成臨界區執行后,將其flag設置為false以釋放臨界區,并將turn設置為1,把權力轉交給P1

    bool flag[2]; int turn; void P0() {while (true){flag[0] = true;while (flag[1]){if (turn == 1){flag[0] = false;while(turn == 1) { /* busy waiting */ }flag[0] = true;}}/* critical section */turn = 1;flag[0] = false;} } void P1() {while (true){flag[1] = true;while (flag[0]){if (turn == 0){flag[1] = false;while (turn == 0) { /* busy waiting */ }flag[1] = true;}}/* critical section */turn = 0;flag[1] = false;} } int main() {flag[0] = false;flag[1] = false;turn = 1;parbegin(P0, P1); // concurrent executionreturn 0; }

    Peterson 算法

    Dekker 算法解決了互斥問題,但復雜的程序很難實現且其正確性也很難證明。Peterson提出了一個簡單且精致的算法。和前面一樣,全局數組變量flag表明每個互斥進程的位置,全局變量turn解決同時發生的沖突。

    bool flag[2]; int turn; void P0() {while(true){flag[0] = true;turn = 1;while(flag[1] && turn == 1) {/* busy waiting */}/* critical section */flag[0] = false;} } void P1() {while(true){flag[1] = true;turn = 0;while(flag[0] && turn == 0) {/* busy waiting */}/* critical section */flag[1] = false;} } int main() {flag[0] = false;flag[1] = false;parbegin(P0, P1); // concurrent executionreturn 0; }

    最后兩種正確算法相關內容(驗證、說明等)待更新… …

    總結

    以上是生活随笔為你收集整理的【操作系统】互斥:软件解决方法的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。