1. 程式人生 > 其它 >作業系統-PETERSON演算法

作業系統-PETERSON演算法

Peterson演算法概述

Peterson演算法是一種實現程序/執行緒間互斥訪問臨界區的演算法。(執行緒間共享記憶體地址空間,程序需要採用共享記憶體實現)

關鍵術語:

臨界區:一段程式碼,程序/執行緒在這段程式碼中程序將訪問共享資源,當另外一個程序已在這段程式碼執行時,其他程序就不能在這段程式碼中執行。

互斥:當一個程序/執行緒在臨界區訪問共享資源時,其他程序/執行緒不能進入臨界區訪問任何其他共享資源的情形。

wiki定義:

Peterson's algorithm (or Peterson's solution) is a concurrent programming algorithm for mutual exclusion that allows two or more processes to share a single-use resource without conflict, using only shared memory for communication. It was formulated by Gary L. Peterson in 1981. While Peterson's original formulation worked with only two processes, the algorithm can be generalized for more than two.

Peterson演算法實現

該演算法使用兩個變數,flagturnflag[n] 值為 true 表示程序 n 想要進入臨界區。turn表示現在輪到誰,是一個程序編號。

int flag[2];
int turn;

void init() {
   flag[0] = flag[1] = 0; // 1->thread wants to grab lock
   turn = 0; // whose turn? (thread 0 or 1?)
}

void lock() {
	 flag[self] = 1; // self: thread ID of caller
   turn = 1 - self; // make it other thread's turn
   while ((flag[1-self] == 1) && (turn == 1 - self))
      ; // spin-wait
}

void unlock() {
	 flag[self] = 0; // simply undo your intent
} 

演算法解釋:

flag[self] = 1 :設定自己程序感興趣,想要訪問臨界區。

turn = 1 - self:將turn設定為對方程序。注意這個turn是個共享變數,若多程序/多執行緒進行訪問,會保留最後一次寫的turn值,前面寫的值被寫覆蓋了(overwriting)。然後是一個自旋等待(CPU空轉,忙等待,busy wait):while ((flag[1-self] == 1) && (turn == 1 - self));

對該自旋等待真值表進行分析,如下:

flag[1-self] == 1 turn == 1 - self 真值 含義
T T T 對方程序也想訪問臨界區,且turn值為自己設定
T F F 對方程序也想訪問臨界區,且turn值為對方設定
F T F 只有自己想訪問臨界區,直接訪問即可。
F F F 只有自己想訪問臨界區,直接訪問即可。

由上述真值表可見,僅有雙方(兩個程序/執行緒)都想訪問臨界區時,才會出現自旋情況。將上述情況以單核CPU情況模擬,有如下兩種情況。

  • P0先寫turn值而P1後寫:P1自旋,P0進入臨界區
Process 0 Process 1 turn值 事件
lock()
flag[0] = 1;
turn = 1;
1 排程程式排程P0執行
lock()
flag[1] = 1;
turn = 0;
while ((flag[0] == 1) &&
(turn == 0));
P1自旋
0 中斷,排程程式排程P1執行
進入臨界區
do something
出臨界區
unlock()
flag[0] = 0;
0 中斷,排程程式排程P0執行
while ((flag[0] == 1) &&
(turn == 0));自旋結束
進入臨界區
do something
出臨界區
unlock()
flag[1] = 0;
0 中斷,排程程式排程P1執行
  • P1先寫turn值而P0後寫:P0自旋,P1進入臨界區
Process 0 Process 1 turn值 事件
lock()
flag[1] = 1;
turn = 0;
0 排程程式排程P1執行
lock()
flag[0] = 1;
turn = 1;
while ((flag[1] == 1) &&
(turn == 1));
P1自旋
1 中斷,排程程式排程P0執行
進入臨界區
do something
出臨界區
unlock()
flag[1] = 0;
1 中斷,排程程式排程P1執行
while ((flag[1] == 1) &&
(turn == 1));自旋結束
進入臨界區
do something
出臨界區
unlock()
flag[0] = 0;
1 中斷,排程程式排程P0執行

由上述例子可見:併發時,兩程序/執行緒中存在著某種搶佔的關係,即誰先寫入turn值,就不會因此而自旋(因為自旋條件為turn為對面值);若不是併發,則可以直接進入,而後上鎖的程序/執行緒則需要等待先上鎖程序/執行緒解鎖。

演算法評價

Peterson演算法是一種不依賴硬體實現的鎖機制。如今大多數CPU以指令亂序執行來提高執行效率,此時實現Peterson演算法就得使用相關記憶體屏障指令。現在一般使用硬體支援的鎖機制(比如test-and-set或compare-and-swap),這些機制往往只需要很少的硬體支援。

reference

[1] wiki

[2] 作業系統導論

[3] 現代作業系統

[4] 深入理解計算機系統