You are on page 1of 35

註:本章學術性較重,但考試常考。

行程的同步

作者 : 陳鍾誠
單位 : 金門技術學院資管系
Email: ccc@kmit.edu.tw
URL : http://
ccc.kmit.edu.tw

日期 : 01/17/10
為何要同步 ?
 為何要同步 ?
 避免競爭情況 (Race Condition)
 方法:鎖定臨界區間 (Critical Section)

 低階的同步方法
 交替演算法 (Turn Algorithm)
 旗標演算法 (Flag Algorithm)
 綜合演算法 (Combination Algorithm)
 麵包店演算法 (Bakery Algorithm)
 硬體支援 (Hardware Support)
 禁止中斷 ( 在臨界區間內 )
 硬體的 Test and set 指令
 硬體的 swap 指令
 高階的同步方法
 號誌 (Semaphore)
 計數號誌 (Counting Semaphore)
 二元號誌 (Binary Semaphore) -- Java
 臨界區域 (Critical Region)
 監督程式 (Monitor) – C#

2 陳鍾誠 - 01/17/10
競爭情況 (Race Condition)
Producer Consumer

while (true) { while (true) {


while (counter == BUFFER_SIZE) while (counter == 0)
; ;
buffer[in] = nextProduced; nextConsumed = buffer[out];
in = (in+1) % BUFFER_SIZE; out = (out+1) % BUFFER_SIZE;
counter = counter + 1; counter = counter - 1;
} }

3 陳鍾誠 - 01/17/10
競爭情況 (Race Condition)
Producer : counter++ Consumer : counter--

LOAD register, counter; LOAD register, counter;


ADD register, 1 SUB register, 1
STORE counter, register STORE counter, register

If counter = 5
then P: LOAD register, counter; register = 5 ;
counter may be P: ADD register, 1 register = 6
4 C: LOAD register, counter register = 5
5 C: SUB register, 1 register = 4
6 P: STORE counter, register counter = 5
After execution C: STORE counter, register counter = 4
4 陳鍾誠 - 01/17/10
避免競爭 1 : 臨界區間
 上述的會產生競爭情況的段落,不能讓多個程式同時執行

 為了確保執行順序不會出問題,我們可以採用臨界區間的方式

do {

entry section

critical section

exit section

remainder section
} while (1)
5 陳鍾誠 - 01/17/10
競爭情況的解決方法
 方法一:用硬體解決
 單一 CPU :
 在一個關鍵段落還沒完成之前,禁止中斷的發生 (Intel 80x86,ARM…)
 利用 test and set 等硬體指令
 多個 CPU : ( 雙核心以上 )
 必須加上旋轉鎖機制 (Linux, Windows) (busy waiting)

 方法二:用軟體解決
 交替演算法 (Turn Algorithm)
 旗標演算法 (Flag Algorithm)
 綜合演算法 (Combination Algorithm)
 麵包店演算法 (Bakery Algorithm)

6 陳鍾誠 - 01/17/10
競爭情況的解決方法必需滿
足下列條件
 互斥 (Mutual Exclusion)

 進行 (Progress)

 有限等待 (Bounded Waiting)

7 陳鍾誠 - 01/17/10
交替演算法
 兩個行程 Pi 及 Pj 之間的臨界區演算法。
 共用一個變數 turn ,指出目前允許進入臨界區的
是哪一個行程。
 只記錄系統目前的狀態,但是並不記錄行程個別的
狀態。
 如果 turn = i ,代表行程 P 可以進入臨界區之
i
中。
 滿除臨界區互斥的條件,但是不能滿足進行的條件。

8 陳鍾誠 - 01/17/10
交替演算法 ( 續 )
 行程 Pi 的程式結構如下:
do {
while (turn != i) ;
critical section
turn = j;
remainder section
} while (1);

9 陳鍾誠 - 01/17/10
旗標演算法
 兩個行程 Pi 及 Pj 之間的臨界區演算法。
 將交替演算法中共有的變數 turn 改為共有的陣列
flag ,記錄系統中個別行程的狀態。
 如果 P 要進入臨界區,則將 flag[i] 設為
i
TRUE 。
 當 P 離開臨界區後,再將 flag[i] 設為
i
FALSE 。
 滿足臨界區互斥的條件,但是仍然無法滿足進行的
條件。

10 陳鍾誠 - 01/17/10
旗標演算法 ( 續 )
 行程 Pi 的程式結構如下:
do {
flag[i] = TRUE;
while (flag[j]) ;
critical section
flag[i] = false;
remainder section
} while (1);

11 陳鍾誠 - 01/17/10
綜合演算法
 兩個行程 Pi 及 Pj 之間的正確臨界區演算法

 綜合交替演算法與旗標演算法。

以 flag 陣列記錄個別行程是否想要進入臨界區;
而 turn 變數指出目前系統允許哪個行程進入臨界
區。
 同時滿足互斥、有限等待與進行三個條件。

12 陳鍾誠 - 01/17/10
綜合演算法 ( 續 )
 行程 Pi 的程式結構如下:
do {
flag[i] = TRUE;
turn = j;
while (flag[j] && turn == j) ;
critical section
flag[i] = false;
remainder section
} while (1);
13 陳鍾誠 - 01/17/10
麵包店演算法
 多個行程間的臨界區演算法。
 以行程取到的號碼牌,由小而大地讓行程進入臨界
區中。
 若有行程取到相同號碼,則以行程的 ID 大小決
定先後順序, ID 較小的優先。
 同時滿足互斥、有限等待與進行三個條件。

14 陳鍾誠 - 01/17/10
麵包店演算法 ( 續 )
 行程 Pi 的程式結構如下:
do {
choosing[i] = TRUE;
number[i] =
max(number[0], number[1], …, number[n – 1]) + 1;
choosing[i] = FALSE;
for (j = 0; j < n; j++) {
while (choosing[j]) ;
while ((number[j] != 0) &&
((number[j], j) < (number[i], i))) ;
}
critical section
number[i] = 0;
remainder section
} while (1);
15 陳鍾誠 - 01/17/10
硬體支援

作者 : 陳鍾誠
單位 : 金門技術學院資管系
Email: ccc@kmit.edu.tw
URL : http://
ccc.kmit.edu.tw

日期 : 01/17/10
硬體支援 1 : 禁止中斷
單 CPU 的系統
 讓行程在修改共用的變數時停止接受中斷而解決同
步的問題。
多 CPU 的系統
 加上旋轉鎖等忙碌等待機制 (busy waiting)

17 陳鍾誠 - 01/17/10
硬體支援 2 : Test-and-Set 指

 在執行完整個指令之前都不會被中斷。

指令會傳回參數 target 目前的值,


 Test-and-Set
並同時將 target 的值設為 TRUE 。
boolean Test-and-Set (Boolean &target) {
Boolean rv = target;
target = true;
return rv;
}

 可以利用 Test-and-Set 指令實作多行程的臨界區


演算法。
18 陳鍾誠 - 01/17/10
硬體支援 3 : Swap 硬體指令
 在執行完整個指令之前都不會被中斷。

指令會交換參數 a 與 b 兩個字元組
 Swap
的內容。
Void Swap (Boolean &a, Boolean &b) {
Boolean temp = a;
a = b;
b = temp;
}

19 陳鍾誠 - 01/17/10
避免競爭 2 : 號誌
Semaphore
 號誌是十分常用的同步工具,可以簡單地解決較為複雜的
同步問題。

 大部分的作業系統都已經實作了號誌,作為行程間同步的工具。

 號誌包含一個數值,該值在初始化之後就只能經由 signal() 與
wait() 兩個不可被中斷的函式去存取。

 當一個行程在存取號誌的值時,其他行程無法存取同一個號誌的
值。

20 陳鍾誠 - 01/17/10
計數號誌的使用 (1)
 解決臨界區間的問題

do {
wait(mutex);
critical section
signal(mutex);
remainder section
}

21 陳鍾誠 - 01/17/10
計數號誌的使用 (2)
 解決同步的問題
P1 P2

wait(mutex) S2
S1; signal(mutex)

22 陳鍾誠 - 01/17/10
計數號誌 – 忙碌等待版
 計數號誌 Counting Semaphore

void wait(s) void signal(s)


{ {
while (s<=0) s++;
; }
s--;
}

23 陳鍾誠 - 01/17/10
計數號誌 – 非忙碌版

void wait(s) void signal(S)


{ {
S.value - -; S.value++;
if (S.value < 0) if (S.value <=0)
block() ; wakeup(p);
} }

24 陳鍾誠 - 01/17/10
二元號誌
 利用硬體實作對二元號誌的支援,簡單又快。

 利用二元號誌再實作計數號誌。

25 陳鍾誠 - 01/17/10
利用二元號誌實作計數號誌

void wait(S) void signal(s)


{ {
wait(S1) wait(S1);
C--; C++;
if (C < 0) { if (C<=0)
signal(S1); signal(S2);
wait(S2); else
} signal(S1);
signal(S1); }
}

26 陳鍾誠 - 01/17/10
以號誌實作生產者 - 消費者問題
 empty 初始化為 n full 初始化為 0
生產者 消耗者
do {
do {
wait(full);

wait(mutex);
產生一個新的項目放在 nextp


將一個項目由緩衝區中
wait(empty);
移到 nextc
wait(mutex);


signal(mutex);
將 nextp 加入到緩衝區中
signal(empty);


signal(mutex);
消耗放在 nextc 中的項目
signal(full);

} while(1);
} while(1);
27 陳鍾誠 - 01/17/10
臨界區域 (Critical Region)
 一種高階的同步方法

 語法
 region V when B do S;
 V : shared T;

 注意 : 必須小心 B 的條件設定,條件相同者不能
保證其執行的先後順序
 例如:
 R1 : region V when true do S1
 R2 : region V when true do S2
 則 R1, R2 不一定誰會先被執行。

28 陳鍾誠 - 01/17/10
以臨界區域實作 : 生產者 - 消
費者
Producer Consumer

region buffer when (count < n) region buffer when (count > 0)
{ {
pool[in] = nextp; nextc = pool[out];
in = (in + 1) % n; out = (out + 1) % n;
count ++; count --;
} }

29 陳鍾誠 - 01/17/10
監督程式 (Monitor)
 監督程式是另外一種高階的同步工具。
 對較複雜的同步問題提供了更一般性的實作工具。
 由一些變數宣告及函式所組成,變數的值定義了監
督程式的狀態。
 保證只有一個行程在監督程式中執行所定義的函式。

 在監督程式中,程式設計師不需要撰寫有關同步的
程式碼,但是可以利用條件變數來定義自己的同步
機制。
 哲學家晚餐問題可以利用監督程式來實作。

30 陳鍾誠 - 01/17/10
結語
 行程不同步可能會產生競爭情況

 為了避免競爭情況必需保護臨界區間

 臨界區間的保護可用行程同步的方式
 Mutex
 Semaphore

31 陳鍾誠 - 01/17/10
比較 - 臨界區域 v.s. 臨界區間
 請注意,臨界區域 (Critical Region) 與 臨界
區間 (Critical Section) 不同

 臨界區間 (Critical Section)


 指的是不可同時執行的該區間

32 陳鍾誠 - 01/17/10
競爭狀況的範例
- RaceCondition.java
import java.util.Random;
class RaceCondition {
public static void main(String[] args) throws Exception {
StepThread.test();
}
}
class StepThread extends Thread {
public static void test() throws Exception {
StepThread a = new StepThread("A", 1);
StepThread b = new StepThread("B", -1);
a.start();
b.start();
a.join();
b.join();
System.out.println("counter="+StepThread.counter);
System.out.println("lines=\n"+StepThread.lines);
} 33 陳鍾誠 - 01/17/10
競爭狀況的範例
- RaceCondition.java
static StringBuffer lines = new StringBuffer();
static int counter=0; int step; String name;
StepThread(String pName, int pStep) {
step = pStep;
name = pName;
}
int register;
public void run() {
for (int i=0; i<10; i++) {
String line = name+" i="+i+" step="+step+"\t before:counter="+counter;
// counter = counter + step;
register = counter;
register = register + step;
counter = register;
line += " after:counter="+counter; // Y[ synchronized hBLX counter | Race Condition
lines.append(line+"\n");
// System.out.println(line);
// }
}
}
} 34 陳鍾誠 - 01/17/10
競爭狀況的範例
- RaceCondition.java

35 陳鍾誠 - 01/17/10

You might also like