轉自:http://blog.csdn.net/speedme/article/details/17595821
- 1. 背景
- 首先,看個例子,進程P1,P2共用一個變量COUNT,初始值為0




因為P1,P2兩個進程的執行順序是隨機的,可能順序執行也可能是並發的,由圖可見,不同的執行順序,COUNT的值會不同,這是不允許的。
像這種情況,及多個進程並發訪問和操作同一數據且執行結果與訪問發生的特定順序有關,稱為競爭條件。
- 2.臨界區域問題
為了避免上述情況的發生於是就引入了臨界區概念。一個系統有n個進程,每個進程有一個代碼段稱為臨界區。這種系統重要特征是當一個進程在臨界區內執行,沒有其他進程被允許在臨界區內執行。
臨界區問題必須滿足三項原則:互斥,前進,有限等待。解釋如下:


- 3.Peterson算法
了解了臨界區之后,那么如何控制兩個進程訪問一個共享的單位用戶資源而不發生訪問沖突。Peterson算法是一個實現互斥所的並發程序設計算法,它很好地解決了這個問題。
先看看兩個非該算法的程序




仔細分析上面兩段代碼可以知道當多進程執行代碼時他們都違反了Progress原則(臨界區三原則)。
Peterson算法代碼如下:很好地滿足了臨界區三原則。
利用了中間值turn,避開了。
pi進程 pj進程(交換i、j位置即可)

偽代碼

java代碼實現
public class Peterson implements Runnable {
private static boolean[] in = { false, false };
private static volatile int turn = -1;
public static void main(String[] args) {
new Thread(new Peterson(0), "Thread - 0").start();
new Thread(new Peterson(1), "Thread - 1").start();
}
private final int id;
public Peterson(int i) {
id = i;
}
private int other() {
return id == 0 ? 1 : 0;
}
@Override
public void run() {
in[id] = true;
turn = other();
while (in[other()] && turn == other()) {
System.out.println("[" + id + "] - Waiting...");
}
System.out.println("[" + id + "] - Working ("
+ ((!in[other()]) ? "other done" : "my turn") + ")");
in[id] = false;
}}
如果想更深入了解Peterson算法可以參觀下下面網址:
上面講到了臨界區,那么就有必要提到臨界資源了。雖然在多道程序系統中的諸進程可以共享各類資源,然而臨界資源卻是一次只能供一個進程使用,使用完后歸還系統,才能給其他進程使用。(例如上面例子中的COUNT是臨界資源)
進程對臨界資源必須互斥使用,為實現臨界資源的互斥訪問,應該保證諸進程互斥地進入自己的臨界區。為此每個進程在進入其臨界區前,必須先申請,經過允許后方能進入。
同步機制應該遵循的准則:
空閑讓進 |
當無進程處於臨界區內時,必須讓一個要求進入臨界區的進程立即進入,以有 效地利用臨界資源。 |
忙則等待 |
當已有進程處於臨界區內時,其它試圖進入臨界區的進程必須等待,以保證它 們互斥地進入臨界區。 |
有限等待 |
對要求進入臨界區的進程,應在有限時間內使之進入,以免陷入“死等”。 |
讓權等待 |
對於等待進入臨界區的進程而言,它必須立即釋放處理機,以免進程“忙等” |
解決互斥的鎖機制:
實現互斥的一種軟件方法是采用鎖機制,即提供一對上鎖和開鎖原語,以及一個所變量W
進入臨界區前,通過所變量來判斷臨界資源是否被占用。
但是鎖機制僅能表示“開”與“關”兩個狀態;開、關原語必須作為原子操作來進行;關鎖原復測試W狀態,浪費了處理機的時間;鎖機制只能解決互斥,不能用於同步。信號同步機制很好地解決了這個問題,下篇博客(
進程同步之信號量機制(pv操作)及三個經典同步問題)將為你詳細解讀信號量機制。
轉載請注明出處:http://blog.csdn.net/speedme
- 頂
- 0