340 likes | 1.76k Views
第六章 並行:死結與飢餓 Concurrency: Deadlock and Starvation. 6.1 死結的原理 死結的定義 一組 process 由於競爭系統資源或彼此溝通所發生的永久懸置狀態。 通常發生時,並無有效率的解決方法。 交通上可能發生死結 ( 圖 6.1a) 、發生死結 ( 圖 6.1b) 。 死結發生在 process 與電腦資源的情形。. Process P … Get A … Get B … Release A … Release B. Process Q … Get B … Get A … Release B …
E N D
第六章 並行:死結與飢餓Concurrency: Deadlock and Starvation 6.1 死結的原理 • 死結的定義 • 一組process由於競爭系統資源或彼此溝通所發生的永久懸置狀態。 • 通常發生時,並無有效率的解決方法。 • 交通上可能發生死結(圖6.1a)、發生死結(圖6.1b)。 • 死結發生在process與電腦資源的情形。 Process P … Get A … Get B … Release A … Release B Process Q … Get B … Get A … Release B … Release A
(a) Deadlock possible (b) Deadlock Figure 6.1 Illustration of Deadlock 2
P和Q需要A 不可避免的死結 P和Q需要B Figure 6.2 Example of Deadlock [BACO93]
圖6.2中,六個不同的執行路徑 • Q Get B => Q Get A => Q Release B => Q Release A • Q Get B => Q Get A => P Get A (blocked) => Q Release B => Q Release A • Q Get B => P Get A; 死結無可避免: Q因等待A而懸置; P因等待B而懸置。 • P Get A => Q Get B; 死結無可避免: Q因等待A而懸置; P因等待B而懸置。 • P Get A => P Get B => Q Get B (blocked) => P Release A => P Release B • P Get A => P Get B => P Release A => P Release B
Process P … Get A … Release A … Get B … Release B Figure 6.3 Example of No Deadlock [BACO93]
資源的分類 • 可再使用的(reusable)資源 • 處理器、I/O通道、主記憶體、輔助記憶體、裝置、檔案、資料庫、號誌(semaphore)。 • 例: 二個process P及Q,相互爭奪Disk(D)及Tape(T): • Process P: Request(D); Lock(D); Request(T); Lock(T); • Process Q: Request(T); Lock(T); Request(D); Lock(D); • 可消耗的(consumable)資源 • 中斷、訊號、訊息、I/O緩衝區的訊息。 • 解決死結的策略:偵查(detection)、預防(prevention)、避免(avoidance)。 Process P1 … Receive(P2); … Send(P2); Process P2 … Receive(P1); … Send(P1);
死結的條件 要發生死結,下列三個狀況必須同時存在: (必要條件,但非充分) • Mutual Exclusion(互斥):一項資源一次只能被一個process使用。 • Hold and wait(佔有並等待):process等待其他資源時,可佔住已配置到的資源。 • No Preemption(不可搶先):被某一process佔用的資源,無法被其他process強制取走。 只有這三個狀況,也有可能不發生死結,死結要發生,需要第四個狀況: • Circular wait(循環等待):process間存在封閉鏈,每一個process至少佔據封閉鏈上,下一個process所需要的資源。 Figure 6.5 Circular Wait
6.2 死結的預防 (deadlock prevention) • 設計一個系統,使得死結發生的可能預先被排除。 • 間接的預防:阻止前三個必要條件之一的發生。 • 直接的預防:阻止循環等待(第4項)的發生。 • Mutual Exclusion(互斥) • 一般而言無法預先排除。例如,即使檔案可以同時多方讀取,但寫入卻具有排他性。 • Hold and wait(佔有並等待) • process須一次請求所有需要的資源。(沒有效率) • No Preemption(不可搶先) • 系統將被某一process佔用的資源,強制取走(釋放資源)。 • Circular wait(循環等待) • 定義一線性順序的資源型態,依此順序請求資源。 (沒有效率)
6.3 死結的避免 (deadlock avoidance) • 死結的預防 vs.死結的避免 • 死結的預防會導致無效率的使用資源、無效率的執行process。 • 死結的避免比預防允許更多的並行(concurrency)。 • 死結的避免:動態決定資源請求是否會導致死結。 • Process Initiation Denial (拒絕啟動process; 於process起始時便予否決) • 如果一個process的需求可能導致死結,則不要開始執行此process。 • Resource Allocation Denial (拒絕配置資源; 於資源配置時予以否決) • 不要准許一個增加資源的請求,如果這個請求有可能造成死結。
Process Initiation Denial • 考慮n個process,m個不同類型的資源。 • Resource = (R1, R2, …, Rm), 系統中每一資源的總量。 • Available = (V1, V2, …, Vm), 未配置給process資源的總量。 每個process對每個資源的需求 Cij:process i要求(claim)的資源型態j 的最大數量。 每個process對每個資源的配置 Aij :process i得到資源型態j 配置的數量。
Cij:process i要求(claim)的資源型態j 的最大數量。 • Aij :process i得到資源型態j 配置的數量。 • 下列關係式成立: 1. , for all i:所有資源不是可使用就是已配置 2. , for all k, i: 任何process要求的資源少於系統中的資源總量 3. , for all k, i: process配置的資源少於其最初要求的資源 • 定義一個死結避免策略: 若process的需求可能導致死結的發生,則拒絕啟動該process。只有在下列情形,才會啟動新的process: , for all i • 只有在目前所有process的最大請求加上新的process(n+1)的最大請求能夠滿足時,才可以啟動process。
Resource Allocation Denial (banker’s algorithm) • 系統的狀態: • 兩個向量:Resource, Available。(整體資源及可用的) • 兩個矩陣:Claim, Allocation。(個別process所請求及已配置的) Resource Vector (a) 起始狀態 Available Vector Claim Matrix Allocation Matrix Available Vector (b) p2執行完成 Claim Matrix Allocation Matrix
安全狀態之判定(在可用的資源下,所有process都能執行完成)安全狀態之判定(在可用的資源下,所有process都能執行完成) Available Vector (b) p2執行完成 Claim Matrix Allocation Matrix Available Vector (c) p1執行完成 Claim Matrix Allocation Matrix Available Vector (d) p3執行完成 Claim Matrix Allocation Matrix
不安全狀態之判定 Resource Vector (a) 起始狀態 Available Vector Claim Matrix Allocation Matrix Available Vector (b) P1要求R1, R3各一單位 Claim Matrix Allocation Matrix • 任一process都至少再需要一單位的R1,卻已沒有可用的R1! • 並非死結,但有發展成死結的可能。
6.4 死結的偵測(deadlock detection) • 死結的預防 vs. 死結偵測 • 死結的預防非常保守:限制資源的取得。 • 死結偵測不會限制資源的取得。process對資源的要求,只要有可用的資源都會獲得准許。 • 死結偵測:每隔一段時間,系統會執行一演算法來偵測循環等待的狀況。 • 死結檢查頻率:每次有資源需求時 • 優點:比較早偵測出死結,演算法相對較簡單。 • 缺點:檢查頻繁會消耗相當多大的處理時間。
死結偵測演算法 • Request Matrix Q; Allocation Matrix A • 藉由對無死結(not deadlocked)的process做記號,最初,所有process都未被做記號。接著執行下列步驟: • 對配置矩陣A中整列(row)為0的每個process做記號。 • 初始化暫存向量W,使它與可用資源向量(Available Vector)相等。 • 找出索引 i,process i未被做記號,且Q的第i列小於或等於W。若找不到這樣的列,則終止演算法。 • 若找到這樣的列,則對process i做記號,並且將配置矩陣的第i列加到W。回到步驟3。 • 死結存在若且唯若(if and only if)演算法最後存在著未做記號的process。 • 演算法的策略: 找出資源需求可被滿足的process,假設這些資源被授與、process能夠執行完成、最後process釋放它所有資源。 • 並不能保證能預防死結,僅是測定死結目前是否存在。
死結偵測的例子 • 標示P4,因為P4並沒有配置到資源 • 設W = (0 0 0 0 1) • Process P3的請求 W,標示P3,並且讓W = W + (0 0 0 1 0) = (0 0 0 1 1) • 終止演算法:最後P1, P2未標示,這些process為死結。 Resource Vector Request Matrix Q Allocation Matrix A Available Vector
死結的回復(Recovery) • 讓所有死結的process流產。(最常使用的方法) • 讓每個死結的process回到之前的某個檢查點(check point),並且重新開始這些process。 • (需要rollback及重新啟動的機制) • 接連的讓死結的process流產,直到死結不再存在。 • 接連的搶佔(preempt)資源,直到死結不再存在。 • 3和4中的選擇 • 目前為止消耗最少的處理器時間。 • 目前為止輸出量最少的。 • 還需要執行最久的。 • 目前為止配置到最少資源的。 • 最低優先權的。
6.5 整合的死結策略 • 不同情況使用不同方法 • 將資源分成不同的類別。 • 將資源類別以線性排序(linear ordering)。 預防死結:打破循環等待(Circular Wait) • 在一資源類別中,使用對這類資源最適合的演算法。 • 舉例: • 置換空間(swap space) :如果最大記憶體需求為已知,將所有可能需使用的資源一起配置,預防死結:打破佔有並等待(Hold and Wait);或者,使用死結的避免。 • process資源:因為需求會預先宣告,可採用死結的避免;或者,使用資源排序 (預防死結)。 • 主記憶體:採取preemption,將佔用的process置換到磁碟,預防死結:打破不可搶先(No Preemption)。 • 內部資源:使用資源排序 (預防死結)。
6.6 哲學家用餐問題(The Dining Philosophers Problem) • 故事背景: • 從前在某個地方,有5個哲學家住在一起,每位哲學家的生活主要由思考(thinking)和用餐構成。 • 所有的哲學家都同意唯一有助於他們思考的食物就是義大利麵條。 • 佈置:圓桌、一大盤義大利麵、一人一個盤子、5支叉子。 • 用餐:使用盤子兩旁的叉子。 • 問題:策劃一個儀式(演算法) 讓哲學家用餐,避免死結及飢餓、滿足互斥。(二位哲學家不能同時用一支叉子) • 可說明死結和飢餓的基本問題,是評估同步(Synchronization)方法的標準測試實例。
解法 • 解法1:使用semaphore,每位哲學家先拿起左邊的叉子,再拿起右邊的叉子,用餐後把叉子放回桌面。 • 死結:所有哲學家一起坐下,拿起左邊的叉子。 • 飢餓:任何哲學家都有可能一直拿不到另一支叉子。 • 解法2:一次只允許4位哲學家用餐,仍使用semaphore。 • 這個方法不會發生死結和飢餓。(semaphore有一blocked queue,依呼叫先後順序排列)
解法2 程式 // program dining_philosophers semaphore fork[5]= {1,1,1,1,1}; semaphore room = { 4 }; int i; void philosopher(int i) { while (true){ think(); wait(room); wait(fork[i]); wait(fork[(i+1)mod 5]); eat(); signal(fork[(i+1)mod 5]); signal(fork[i]); signal(room); } } void main() { parbegin( philosopher(0), philosopher(1), philosopher(2), philosopher(3), philosopher(4) ); }
6.7 Unix 並行機制 • 管線(pipe) :讓二個process以生產者-消費者的模式溝通。 • 堪稱UNIX對作業系統最大的貢獻。 • 一環狀的緩衝區,先進先出佇列;某一process寫入,另一process讀出。 • 沒有足夠空間寫入或沒有資料讀取時,process被懸置(blocked)。 • 依命名方式分為:命名(named)、未命名(unnamed)。 • 訊息(message) :一個伴隨訊息類型的文字區塊。 • msgsnd:傳遞訊息;msgrcv:接收訊息。每一process有一訊息佇列(功能類似信箱) 。 • 寄訊息者(sender)會詳加說明訊息的類型;接收者(receiver)可依先進先出或訊息的類型來接收訊息。 • 送訊息到已滿的佇列或讀取空佇列的訊息,process將被懸置(blocked)。(若只是試圖讀取,不會遭懸置)
Unix 並行機制 (續) • 共享記憶體(shard memory) • 一塊普通的虛擬記憶體。因process而異,可以是唯讀(read-only)或讀寫(read-write)。 • 互斥機制並不是由共享記憶體提供,但使用時必須有此機制。
Unix 並行機制 (續) • 號誌(semaphore):wait 及 signal運算的一般化(generalization) • 號誌的組成:號誌目前的值、上一個進行運算的process ID、等待號誌值大於目前值的process數量、等待號誌值為0的process的數量。 • semctl:設定一組號誌集合(a set of semaphores)的值; • semop(semaphore s, int sem_op):提供全部semaphore功能。 • sem_op > 0:核心程式增加號誌的值,並且喚醒所有等待號誌值增加的process。 s.count += sem_op; signal(s.count > 0); • sem_op = 0:wait(s.count == 0); • sem_op < 0, |sem_op| s.count:s.count += sem_op; if (s.count == 0) signal(s.count ==0); • sem_op < 0, |sem_op| > s.count: s.count += sem_op; wait(s.count > 0)。
Unix 並行機制 (續) • 訊號(signal) • 軟體的機制,通知process非同步事件的發生。 • 類似硬體的中斷,但不使用優先權。 • 訊號由單一位元所控制。 • 訊號的處理時機:process醒來要執行時或任何process從系統呼叫返回時。
6.8 Solaris Thread 同步原理 • 互斥鎖(mutual exclusion lock) • mutex_enter():獲得此鎖,可能因已被佔有而遭阻擋。 • mutex_exit():釋放此鎖,可能因而拯救一受阻擋的process。 • mutex_tryenter():若鎖未被佔有,則獲得此鎖。(a non-blocking way of performing the mutual exclusion function. This enables the programmer to use a busy-wait approach for user-level threads, which avoids blocking the entire process because one thread is blocked.) • 號誌 • sema_p():wait。 • sema_v():signal。 • sema_tryp():若不會遭懸置,則減少號誌的值。(Decrements the semaphore if blocking is not required)
Solaris Thread 同步原理 (續) • 多讀單寫鎖 • rw_enter(): 獲得讀或寫的鎖。 • rw_exit(): 釋放讀或寫的鎖。 • rw_tryenter(): 若未阻擋則獲得此鎖。 • rw_downgrade(): 寫入鎖定 -> 讀取鎖定。 • rw_upgrade(): 讀取鎖定 -> 寫入鎖定。 • 條件變數 • cv_wait(): 遭阻擋直到條件signaled。 • cv_signal(): 喚醒一個在cv_wait()中遭阻擋的thread。 • cv_broadcast(): 喚醒所有在cv_wait()中遭阻擋的thread。
6.9 Windows 2000 並行機制 • W2K Executive使用同步化的物件家族: • process, thread, file, console input, file change notification, event, • mutex: 一次一個thread使用。 • semaphore: 典型的semaphore。 • waitable timer: 某個時間或固定一段時間發出訊號。