THU_C3 - 【考型 1】Critical section 【考型

Info iconThis preview shows page 1. Sign up to view the full content.

View Full Document Right Arrow Icon
This is the end of the preview. Sign up to access the rest of the document.

Unformatted text preview: 【考型 1】Critical section 【考型 1.1】解決臨界區間必須要解決三個問題 1. mutual exclusion 2. progress 3. bounded waiting 【考型 1.1.1】mutual exclusion 定義 對共享資源或 C.S. 區域,一個時間點內最多只允許一個行程使用或進入,不允許兩個以上的行程同時 使用或同在 C.S. 中,其它想使用或進入 C.S. 的行程必須等待。資源必須是不可共用的形式,若別的 行程想使用這資源,必須延遲至此項資源被釋放後才行;不可共用的資源,互斥的條件必定成立。 【考型 1.1.2】bounded waiting 定義 執行緒要求進入其臨界區間內,而此要求尚未被答應之前,允許其它的執行序進入其臨界區間的次數, 有一個限制。這項限制可避免其它執行緒產生 starvation,也避免有行程需要服務,卻不能得到服務。 【考型 1.1.2.1】剛離開的行程不能加入選擇下一個進入 C.S. 的原因 對於 progress 而言是為了減少 decision time,最重要的是要避免不公平的情形發生,以滿足 bounded waiting 的需求。 【考型 1.1.3】Critical section 定義 當 n 個行程具有共享的 memory variables 進行溝通時,各行程皆有一段稱為 C.S. 的 code,其中行程 可以修改、存取其共同變數、表格、檔案等。而各行程在 C.S. 的活動必定是 mutual exclusion。一個程 式區域一次只允許一個行程去執行,稱此區域為 critical section。 【考型 1.1.3.1】Critical section problem 描述 若行程間採用 shared-memory 方式溝通,為防止不正當的交叉錯誤執行,需將共用的資料置入 C.S. 中;C.S. 的 entry 和 exit 設計需滿足三項性質:mutual exclusion、progress、bounded waiting。 【考型 1.1.3.2】需要支援的 critical section 類型(逢甲) 需要作業系統支援的:Testandset 需要程式語言支援的:semaphore、critical region、monitor 【考型 1.1.4】progress 定義 若沒有執行緒在臨界區間內執行,同時有某一執行緒想要進入其臨界區間,只有那些還未在臨界區間執 行過的執行緒才能決定誰將在下一次進入臨界區間內,並且這個選擇不得無限期延遲下去;臨界區間沒 人進入時,只有要等待進入臨界區間的那些行程,才能決定誰可以進入臨界區間。 【考型 1.1.5】synchronized Java 中的物件都配有一個鎖。當方法被宣告為 synchronized 時,呼叫它的方法必須要擁有這個物件的 鎖;如果鎖已被某個執行緒擁有,則呼叫的執行緒將會被阻隔,而放入到此物件的 entry set。鎖擁有權 的同步機制會造成 deadlock 的情形。以 Producer-Consumer Example 為例,假設緩衝區已滿,而消費 者正在睡覺,當生產者呼叫到 enter 方法時,它看到緩衝區滿了就執行 yield 方法;生產者事實上仍然 擁有這個物件的鎖。當消費者醒來,並試著呼叫 remove 方法,但是它無法取得物件的鎖,所以被阻隔, 則生產者和消費者都不能執行。所以藉由宣告每一種方法為同步的,可以避免對共用變數的競爭現象, 但是 yield 的出現導致可能死結。為了解決這個問題,引進了兩個方法:wait 和 notify。每個物件都有 一個 wait set。當執行緒進入同步方法時,它就擁有該物件的鎖,此時執行緒可決定它要不要繼續執行, 當呼叫 wait 方法時,該執行緒會釋放出物件的鎖,並且設定為阻隔狀態,然後放到等待集合中。因此 當生產者呼叫了 enter 方法發現緩衝區已滿,呼叫 wait 方法,釋放掉該物件的鎖並把生產者放到物件 的等待集合中。然後消費者可以呼叫 remove 方法,並且釋放掉緩衝區的空間給生產者。notify 方法會 從等待集合的一系列執行緒中選擇任何一個執行緒 T,並把 T 從等待集合移到進入集合,再設定 T 的 狀態由阻隔變成可執行。T 就可以和其它的執行緒爭鎖。因此整個流程就是: Edited by Hongjie Dai 1 of 19 生產者呼叫 enter 方法看到鎖可以取得,進入方法中。若判斷緩衝區滿了,就呼叫 wait: 釋放出物件的鎖 設定生產者的狀態為阻隔,並且將生產者放到物件的等待集合 2. 消費者最終因取得鎖而呼叫 remove 方法,從緩衝區移去一項資料而後呼叫 notify(此時消費者仍 然擁有物件的鎖) 3. notify 呼叫把生產者從物件的等待集合移到進入集合,並且設定狀態為可執行 4. 消費者離開 remove 方法。離開方法時就釋放了物件的鎖 5. 生產者試圖重新取得鎖並且成功了,回到呼叫 wait 的地方繼續執行。檢視 while 迴路發現緩衝區 有空間所以繼續 enter 方法的其餘部分。因為沒有執行緒在物件的等待集合,所以 notify 呼叫就 省略了。當生產者從方法離開時,釋放了物件的鎖。 JVM Monitors 程式採用 signal-and-continue 的方法。平行行程互斥存取的解決方法有: 1. 硬體指令:如 Test-and-set、SWAP 2. 系統呼叫:如 P、V、semaphore 3. 軟體演算法:如 Dekker’s algorithm 【考型 1.1.5.1】同步的定義 當許多行程合作完成某些 task 的過程中,因為某些資訊狀態而被迫等待其它行程執行完動作後,才得 以繼續執行,稱為同步。 1. 【考型 1.1.5.2】解決行程同步的方法有哪些 1. algorithm based solution:比如 bakery’s algorithm。缺點是演算法方式的解決方法完全由程式設計者 負擔,不易寫出正確的演算法來滿足臨界區間的三個性質 2. Hardware Instruction support:有些機器會提供一些不可分割執行的指令,例如 test-and-set 或是 SWAP 來簡化設計。優點是簡化臨界區間的設計,例如對 Pi 而言: repeat while test-and-set(Lock) do no-op C.S. Lock=false; R.S. 缺點是不一定機器皆提供這種硬體支援,且不滿足 bounded waiting 3. Semaphore 4. monitor 5. critical region 【考型 1.1.5.2.1】Bakery algorithm 【考型 1.1.5.2.1.1】解釋 Bakery 演算法,考慮程式 假設有家麵包店,每天限量推出特製的麵包,免費送完為止,但每人只能得一個,吸引了許多人前來排 隊。為了解決這個問題,提出一個方法:每個人都要在門外先抽號碼,先抽到的可以到店裡挑你要的口 味。假定規則是:每個人抽的號碼一定要比以進去店裡挑口味的那位的號碼大一號,假設有二個人同時 搶到一樣的號碼時,則讓給年齡比較小者。 do{ 1. choosing[i] = true ; // 假定規則:排最前面的人才有資格抽號碼(這個規則是我定的不是程式定的; // 也可以定成穿得最辣的最有資格抽) 2. number[i] = max(number[0],number[1],...,number[n-1])+1 ; choosing[i] = false ; Edited by Hongjie Dai 2 of 19 // 有資格後就去抽,依店的規則,你抽的號碼要比以進去那位大一號, // 抽完當然要把抽的機會讓給下一位,所以 choosing[i] = false ; 3. 4. // // // for(j=0 ; j<n ; j++){ while ( choosing [ j ] ) ; // no-op while ( ( number [ j ]! = 0 ) && ( number [ j ], j ) < ( number [ i ], i ) ) ; // no-op } 為了小心起見,抽完還要跟週圍以抽過號碼者確認一下,看看你是不是最小號 如果還有人還在抽,就稍等一會,大家抽完再來比對。 如果不小心二人同時抽到同一號碼時,拿出身份證來比誰的年齡小。 CRITICAL SECTION 5. number[i] = 0 ; REMAINDER SECTION }while(true) ; // 比完了,就讓最小號,且年齡是較小者進去挑他要的口味,選完就可以離開了。 // 但是要把記得把號碼牌歸還:number[i] = 0 ; Bakery algorithm 對於 n 個行程的臨界區間設計,拿到最小號碼的行程得以進入臨界區間。若有多個行 程拿到相同的號碼牌,則以 process id 最小者優先進入臨界區間。 當第 3 行移除時,會造成違反 mutual exclusion。 P0 1. 3. 4. 5. 執行第 3 行,挑選 max(order[i]),假設 max 為 0,則 max+1 但尚未 assign 給 order[0] P1 2. 同 step1,max 為 0,max+1 且 assign 給 order[1] P1 進入 C.S.(因為其它行程的 order 皆為 0) P0 執行 order[0]=1 通過第 4 行的測試進入 C.S.(因為 (order[0],0)<(order[1],[1])) ,故 P0、P1 皆進入 C.S. 【考型 1.1.5.2.1.2】寫出 Bakery 演算法,並證明可以解決臨界區間的問題 1. 滿足 mutual exclusion:若多個行程欲進入臨界區間(表 number 值 > 0) ,則具有最小的號碼才 得以進入臨界區間;若具有最小號碼的行程不只一個,則具有最小的行程 ID 者,得以進入臨界區 間,且是唯一的(因為行程 ID 是唯一的) 2. 滿足 progress:不想進入臨界區間的行程 i,它的 number [ i ] = 0,不會使得其它欲進入臨界區間 的行程卡在 for 迴圈中,所以 Pi 不會妨礙別人進入臨界區間;在有限的時間內,必定有一個號碼 值最小者(或號碼最小相同但行程 ID 最小) 得以離開 for 迴圈進入臨界區間中 , 3. 滿足 bounded waiting:若 n 個行程欲進入臨界區間,則具有最小號碼牌得以進入臨界區間,令其 為 Pi。若此時號碼牌最大值為 m,則當 Pi 進入臨界區間離開臨界區間,又馬上企圖進入臨界區間 時,其號碼值必定為 m+1,必不會比擁有 m 號的行程小,所以行程至多等待 n-1 以後即可進入 臨界區間。 【考型 1.1.5.2.1.3】何種情形下會造成兩個行程拿到相同的號碼 當兩個行程同時在抽號碼時,P0 正在抽的途中,並且抽到但是尚未指定給 P0 時,P1 也去抽,結果造 成抽到跟 P0 相同的號碼。 【考型 1.1.5.2.2】Test-and-set(TSL) 一道不可分割的硬體指令,能讀出一個變數把此變數值存於一個區域,再設定此變數成某一個值。例如: Testandset(a, b) 表示讀布林變數 b,把值存到 a,最後再設定 b 的值為真;也可以利用 SWAP(a, b) 的 硬體指令把布林變數 a、b 交換,達到相同的效果。使用硬體指令 Testandset 的方法有下列特點: 因為為不可分割的硬體指令,所以可以達到 mutual exclusion Edited by Hongjie Dai 3 of 19 當多個平行行程要進入臨界區域時,先執行 Testandset 指令者可以先進入臨界區域 要進入臨界區域需要重複執行 Testandset,會造成 busy waiting,而且可能無限延遲、也不一定保證 progress 【考型 1.1.5.2.2.1】硬體指令設計 C.S. 用 SWAP 硬體指令來時作臨界區間問題 // 應用在 C.S. 設計上,對於行程 Pi 片段程式碼 repeat // 先定義 SWAP procedure SWAP(var a, b: Boolean) var temp = Boolean; begin temp = a; a = b; b = temp; end end key = true; repeat SWAP(Lock, key); Until key = false; C.S. Lock = false; R.S. Until fasle // key:區域變數 // Lock:全域變數,初始為 false 不滿足 Critical section 中的 bounded waiting 條件。 【考型 1.1.5.2.2.2】硬體指令實作 semaphore wait(s): repeat while Testandset( LOCK) do no-op; while S <= 0 do no-op; S = S-1; LOCK = false; R.S. until false signal(s): repeat while Testandset( LOCK ) do no-op; S = S+1; LOCK = false; R.S. until false 【考型 1.1.5.2.3】semaphores 號誌主要的缺點就是需要 busy-waiting,此種類型的號誌也稱為 spinlock。為了解決這個問題,修改號 誌的 P 和 V 運算的定義為一整數值和一個串列的行程,當一行程等候號誌時就將其加入此行程串列之 中。而 V 運算可以把一行程自等候處理串列中移出並喚醒之。 P(S){ value--; if(value < 0){ add this process to list block; } } } } V(S){ value++; if(value≦0){ remove a process P from list wakeup(P); 其中的 block 運算使得呼叫它的行程暫停,而 wakeup(P) 運算則回復被阻隔的行程 P 的執行,這兩種 運算由作業系統以基本的系統呼叫形式所提供。跟忙碌等待的號誌比較起來,其傳統的定義號誌的值永 Edited by Hongjie Dai 4 of 19 遠不會是負值,但是新的實作將會有可能產生負的號誌值,而且其大小剛好為等待此號誌的行程數目。 在等待行程的串列可以很容易的製作在 PCB 中的鏈結區,故每個號誌應含有一整數值與一個對 PCB 串列之指標。 使用等待佇列製作訊號可能導致有兩個或兩個以上的行程等待一項僅能由等待行程所引發的事件(事件 是指一個 V 運算的執行)的情形,而當上述情形發生時,稱這些行程被打了 deadlocked。 製作信號的兩個運作時,有下列特點: 用硬體的 Testandset 指令或是軟體演算法 Dekker ’s algorithm 來製作都會有 busy waiting 的問題 製作成一個被保護的變數 count,和一個 queue 存放等待 V 運作的行程 用作業核心製作可以避免因為 busy waiting 造成 CPU 時間的浪費 使用信號方法有下列特點: 因為信號 P 與 V 為不可分割的運算,所以可以確保達到 mutual exclusion 當多個平行行程要進入臨界區域時,先執行 P 運作者可以先進入臨界區域 當多個平行行程要進入臨界區域時,因為有 queue 可以避免造成 busy waiting,而且在 queue 中 的行程以 FIFO 的方式可以避免 starvation 【考型 1.1.5.2.3.1】semaphore 定義 號誌 S 是一個被保護的整數變數,為一種 ADT,除了初值(給予初值稱為 semaphore-initialize) 只能 , 藉由 wait 和 signal 兩個不可分割的標準運算(P 與 V 兩個運算)來存取,這兩個運作由作業系統以 基本的系統呼叫形式所提供。 P 和 V 的傳統定義為: P(S){ while S≦0 do no_op S=S--; } V(S){ S=S+1; //不可中斷執行 } //不可中斷執行 //不可中斷執行 P 和 V 兩個運算是以不可分割的方式來執行修正號誌的整數值。因此當一個行程修正號誌時,無其它 行程可同時去修正此號誌。此外當 P(S) 的情況下,S 整數值的測試(S≦0) ,和它可能的改變(S--) 也必須不被中斷的執行。 【考型 1.1.5.2.3.2】semaphore 和 monitor 比較 Semaphore 未確保 mutual exclusion 特質 Monitor Mutual exclusion 已獲得保證,程式設計者不需 刻意提出 較 monitor 低階,為一個簡單整數變數,提供 wait 和 高等的資料結構類型,由共享的資料,狀態變 signal 操作 數及一組程序所構成 程式設計師對於 signal 和 wait 誤用仍會造成 mutual exclusion 違反及死結的問題 程式設計師僅需專心於同步問題的解決,不必 擔心違反 mutual exclusion 【考型 1.1.5.2.3.3】Counting Semaphore 和 binary semaphore Counting Semaphore 的數值可以延伸到一不受限的範圍,用來控制存取由有限個數組成的資源。號誌初 值設定為可用的資源數目,希望使用資源的執行緒就對號誌執行一次 P 操作,當執行緒釋放資源時就 執行一次 V 操作。當號誌的數值為零時,則所有的資源都在使用中。接下來希望使用資源的執行緒就 被阻隔住,直到號誌計數值大於零為止。 Edited by Hongjie Dai 5 of 19 P(S): if S.count > 0 then S.count = S.count - 1 else (wait on S.queue) V(S): if( one or more processes are waiting on S.queue ) then ( let one of these processes proceed ) else S.count = S.count + 1; Binary Semaphore 的數值只能是 0 和 1。使用二進制號誌控制存取臨界區間的策略如下(假設號誌初 值設為 1) : Semaphore S; P(S); criticalSection(); V(S); 因此可以使用號誌控制一個行程或執行緒對於臨界區間的存取。 【考型 1.1.5.2.3.3.1】利用 binary semaphore 製作 counting semaphore S1=1, S2=0; wait(C):: // 作 P 運算 wait(S1); C := C - 1; // count 減一 signal(C):: // 作 V 運算 wait(S1); C := C + 1; if C <= 0 then signal(S2); // 有人在等待,將其喚醒 signal(S1); if C < 0 then // 假如 count < 0 則 block begin signal(S1); wait(S2); // 等候 end; else signal(S1); 【考型 1.1.5.2.3.4】busy-waiting 在多元程式規劃系統中,忙碌等待會浪費 CPU 可讓給其它行程使用的時間。可藉由行程自我 block 來 取代忙碌等待。比如在 Java 中呼叫 Thread. yield() 方法。當執行緒呼叫 yield 方法時,此執行緒停留 在可執行狀態,但是可以讓 JVM 選擇其它可執行且優先順序相同的執行緒執行。yield 方法比忙碌等 待讓 CPU 更有效率。當執行緒位於臨界區間時,其它欲進入臨界區間的執行緒必定在入口的程式碼形 成迴路,這種類型的 semaphore 稱為 spinlock。 【考型 1.1.5.2.3.4.1】busy-waiting 何時有用 busy waiting 是以 while loop 的執行將行程卡在 C.S. 的 entry section 中,故 waiting processes 會佔用 CPU time 以執行 while 敘述,造成 CPU time 浪費。但由於其不用 context switching,因此若行程進入 C.S. 中時間很短,很快即會釋放 lock 時,就可以使用 busy waiting。忙碌等待是無法完全避免的。 【考型 1.1.5.2.3.4.2】busy-waiting 定義 一個行程正在等候一個事件發生。 【考型 1.1.5.2.3.4.3】busy-waiting 和 blocking 的差別 blocking 不會和其它行程搶 CPU,避免 CPU time 浪費在沒有意義的 waiting loop 中,但須付出 context switching 的代價。 【考型 1.1.5.2.3.5】何時作業系統會禁止中斷發生以實作 semaphore 單處理器環境中,在執行 wait 和 signal 運算時,禁止中斷發生,如此確保兩運算的執行是不可分割的。 因為一但 disable interrupt,則不同行程的指令不會被交插執行。在多處理器的系統中,則無法靠禁止中 斷控制 C.S.。號誌執行最重要之處在於它們是以不可分割方式執行,也就是必須保證不會有兩個行程同 Edited by Hongjie Dai 6 of 19 時去執行同一號誌 P 與 V 運算(P 與 V 運作的不可分割性質) 。算是一種 Critical Section Problem, 可以用兩種方式解決: 單處理機的環境中,可在執行 P 與 V 的運算時禁止中斷的產生來解決這個問題。因為在單處理機 的環境中,一但中斷被禁止,則不同行程的指令不會被交叉執行。只有目前執行的行程可以執行, 直到中斷再度被允許,然後排班程式才能重新得到控制權 在多處理機的環境之中,以靜止中斷的方式無法解決,因為來自不同行程的指令可以任何方式交叉 執行。若是硬體不提供任何特殊指令,可以用在臨界區間中含有 P 與 V 程序的軟體方式(busy waiting)來解決臨界區間的問題,比如使用 spinlock 【考型 1.1.5.2.4】monitor 監督器是由 Concurrent Pascal 提供的一個分配共用資源的平行結構,同時也屬於一種抽象化資料型態, 因此監督器包括:共用資源的表示與完成分配共用資源的程序。 一個監督器有下列特徵: 平行行程要求分配共用資源時,需要呼叫監督器入口程序,歸還資源時也要呼叫監督器入口程序 一次只允許一個行程進入,達到互斥存取的要求 一種抽象化的資料型態,所有資料只能在監督器內取用,易於發展可靠的軟體系統 利用 wait 指令讓行程暫時在監督器外等待;利用 signal 指令讓在外等待的工作元進入監督器 提供 condition variable 與 wait 及 signal 一起使用,可以允許行程有不同的等待原因,每個原因 賦予一個條件變數,當定義一個條件變數時,同時也建立一個 queue 指令 x.wait 表示執行此操作的執行緒被暫停,直到其它執行緒執行 x.signal。x.signal 運作每次只能恢 復一個等待執行緒的動作。如果沒有任何等待執行緒存在,則此 signal 運作將不產生任何作用,其對 應的 x 的狀態,就跟沒有執行緒運作時一樣,這一點跟號誌的 V 運作比較是有差別的。V 運作只要一 執行,就必定改變號誌的狀態。假設執行緒 P 執行 x.signal 運作,而在條件 x 下等候的有一個執行緒 Q。這時如果允許等候執行緒 Q 恢復執行,則發出訊號的執行緒 P 就必須等待;否則 P 和 Q 便會同 時在監督程式內運作。原則上這兩個執行緒任何一個都可以繼續執行緒,一般的處理方法下列兩種: 1. signal-and-wait:P 等候 Q,直到 Q 離開監督程式,或是等候其它條件成立為止 2. signal-and-continue:Q 等候 P,直到 P 離開監督程式或等候其它條件成立為止 signal-and-continue 方法較為人接受,因為執行緒 P 已經在監督程式內執行著,可以避免不必要的內容 轉換。但如果允許執行緒 P 繼續執行,則等到執行緒 Q 恢復執行時,原先 Q 所等候的邏輯條件,可 能又改變了。Monitor 是一種程式語言架構,compiler 對於呼叫 monitor 程序的處理不同於一般的程序 呼叫: Monitor 內互斥的實作取決於編譯器, 通常是用 binary semaphore。由於編譯器已經安排好了互斥,使得 出錯的機會更少。寫 monitor 的程式設計師不用知道編譯器是怎麼安排互斥的,只要將所有的臨界區間 寫入 monitor,就不用擔行同時有兩個以上的行程進入臨界區間。WAIT 用於使行程停滯以等待某個指 定的 condition variable 出現,SIGNAL 則喚醒一個在停滯以等待指定的 condition variable 出現的行 Edited by Hongjie Dai 7 of 19 程。要避免操做 WAIT 而停滯的行程在被 SIGNAL 喚醒後,與操作 SIGNAL 的行程同時運作於 monitor 中, 有下列兩種方式: 1. 讓剛醒來的行程運作,而暫停其它的行程 2. 要求操作 SIGNAL 的行程必須立即離開 monitor,也就是說 SIGNAL 敘述只可以出現在 monitor procedure 的最後一行 如果 SIGNAL 所操作的條件變數有好幾個行程都在等待,為了避免多個行程同時運作於 monitor 中, 因此只有其中一個行程可以 wakeup,由排班程式來決定哪一個行程 wakeup。條件變數並不是計數器, 它並不像 semaphore 一樣累計 SIGNAL 以供未來使用,因此若操作 SIGNAL 於一個沒有行程在等待 的條件變數上,SIGNAL 會遺失,所以 WAIT 必須操作在 SIGNAL 之前。monitor 與 semaphore 共同 遭遇的問題:monitor 與 semaphore 都是被設計來解決一或多個 CPU 存取 common memory 的 mutual exclusion 問題,對於每個 CPU 皆擁有本身記憶體而以網路連接起來的分散式系統就無法作用; semaphore 的層次太低,而 monitor 又受到程式語言的限制,對於不同機器間的資訊交換皆無法作用。 【考型 1.1.5.2.4.1】monitor 相對於信號的優點 雖然 semaphores 提供了行程同步方便和有效率的機能,但是不正確的使用依然會造成時序的錯誤。為 了處理可能犯的錯誤,發展一個高階語言同步的結構稱之為監督程式。monitor 保證了 mutual exclusion,並防止程式設計師誤用信號而造成違反互斥及死結的問題。 【考型 1.1.5.2.4.2】semaphore 誤用的可能情形(清大) 1. 一個行程對調了 P 和 V 的順序: mutex.V(); criticalSection(); mutex.P(); 結果可能造成同時有數個行程在它們的臨界區間執行,違反了 mutual exclusion 的要求 一行程用 mutex.V() 把 mutex.P() 取代 2. mutex.P(); criticalSection(); mutex.P(); 這種情況可能發生 deadlocked 3. 一行程省略了 mutex.P() 或 mutex.V(),在這種情形下不是違反互斥就是發生死結 【考型 1.1.5.2.4.2】利用 semaphore 模擬 monitor(清大) // 宣告 semaphore 如下: mutex : semaphore // 初值為 1 next : semaphore // 初值為 1 x-sem : semaphore // 初值為 0 // 整數如下: next-count = integer// 初值為 0 x-count = integer // 初值為 0 // 則對 monitor 內每個 function F 製作如下: wait (mutex) BODY OF F If next-count > 0 then signal (next) else signal (mutex) // 對 condition variable X 製作如下: Edited by Hongjie Dai 8 of 19 x-wait: x-count = x-count + 1 if next-count > 0 then signal(next) else signal(mutex) wait(x-sem) x-count = x-count - 1 x.signal: if x-count > 0 then begin next-count = next-count + 1 signal(x-sem) wait(next) next-count = next-count – 1 monitor 的特性本身就已經確保了 mutual exclusion,所以利用 semaphore 製作 monitor,互斥的因素就 必須考慮,因為是 programmer 的責任。也就是說在同一個時間,只能允許一個 process 在 monitor 內 活動,當 process 在 monitor 內執行 x.wait 或 x.signal,就必須把自己關進 queue(wait) 時 signal ,同 一個原本在 queue 中等待的 process,所以無論如何一次只能 wakeup 一個 process。 【考型 1.1.5.2.4.3】monitor 的功能 高階的同步結構,由 local data、procedures 及 initial section 組成 local data 不能由外界直接存取,僅能經由 monitor 內的 procedure 存取 保證 mutual exclusive property,programmer 不需額外的 coding 負擔 提供 condition type 變數供 programmer 解決同步問題 【考型 1.1.5.3】Dekker ’s algorithm 第一個使用軟體有效解決互斥存取問題的是 Dekker(只適用於 2 個行程) 。這裡引進行程處理的控制 結構,這些成對出現的指令稱為 parbegin/parend 或者是被稱為 cobegin/cdend。在 parbegin/parend 之間 所表示的指令就是可以同時執行的指令。下面是一些曾提出的方法: 1. 利用 process_number 表示進入臨界區域的順序,特點有: I. 符合 mutual exclusion:進入臨界區域以前以 while 測試,當 process_number 等於自己表示可 以進入臨界區間,否則必須 block 在迴圈。離開區域時,設定 process_number 為令一個平行 行程,表示第一個平行行程和第二個平行行程需要一前一後、交互輪流的進入臨界區間 II. 不符合 progress:第一個行程和第二個行程需一前一後的交互輪流進入臨界區間;當其中一個 行程結束執行後,令一個行程將無法進行(比如三個 process,p1、p2、p3。當 p1 進入 C.S. 後 設定 next 為 2;p2 進入後設定 next 為 1。如果 p1 結束後,2 進入,則 p3 無法進行,因 為沒有 number design) procedure process_one begin while true do begin while process_number = 2 do no_op; C.S. process_number = 2; R.S. end end begin process_number = 1 parbegin process_one; Edited by Hongjie Dai 9 of 19 procedure process_two begin while true do begin while process_number = 1 do no_op; C.S. process_number = 1; R.S. end end process_two; parend; end 2. 利用兩個布林變數 p1_inside、p2_inside 控制進入的順序,改進前一個方法必須交互進入的缺點。 特點有: I. 不一定保證 mutual exclusion II. 符合 progress procedure process_one begin while true do begin while p2_inside do no_op; p1_inside=true; C.S. p1_inside=false; R.S. end end procedure process_two begin while true do begin while p1_inside do no_op; p2_inside=true; C.S. P2_inside=false; R.S. end end begin p1_inside=false; p2_inside=false; parbegin process_one process_two parend end 3. 為了改進方法 2 中不一定保證達到互斥存取的缺點,將布林變數放在 while 之前。特點如下: I. 符合 mutual exclusion II. 符合 progress III. 可能造成 deadlock var FLAG[1],FLAG[2]:Boolean begin FLAG[1]=false; FLAG[1]=false; parbegin process_one process_two parend end Edited by Hongjie Dai 10 of 19 procedure process_one begin while true do begin FLAG[1]=true; while FLAG[2] do no_op; C.S. FLAG[1]=false; R.S. end end 4. procedure process_two begin while true do begin FLAG[2]=true; while FLAG[1] do no_op; C.S. FLAG[2]=false; R.S. end end 改進方法 3 中可能造成死結的缺點,等待一段時間就讓另一個行程有機會進入其臨界區間。特點 如下: I. 符合 mutual exclusion II. 符合 progress III. 避免造成死結,但可能有 indefinite postponement var FLAG[1],FLAG[2]:boolean procedure process_one begin while true do begin FLAG[1]=true while FLAG[2] do random(FLAG[1]=false/true) C.S. FLAG[1]=false; R.S. end end begin FLAG[1]=false; FLAG[2]=false; parbegin process_one; process_two; parend; end 5. 利用優先權設定改進方法四可能造成的無限延遲的缺點(Dekker ’s algorithm) var TURN(1,2); var FLAG[1],FLAG[2]:boolean begin Edited by Hongjie Dai 11 of 19 procedure process_two begin while true do begin FLAG[2]=true while FLAG[1] do random(FLAG[2]=false/true) C.S. FLAG[2]=false; R.S. end end FLAG[1]=false; FLAG[2]=false; TRUN=1; parbegin process_one; process_two; parend end procedure process_one begin while true do begin FLAG[1]=true; while FLAG[2] do if(TURN=2)then begin FLAG[1]=false; while TURN=2 do no_op; FLAG[1]=true; end C.S. FLAG[1]=false; R.S. end end 6. end end procedure process_two begin while true do begin FLAG[2]=true; while FLAG[1] do if(TURN=1)then begin FLAG[2]=false; while TURN=1 do no_op; FLAG[2]=true; end C.S. FLAG[2]=false; R.S. Dijkstra 對於 Dekker ’s algorithm 改寫,特點如下: I. 符合 mutual exclusion II. 符合 progress III. 符合避免 bounded waiting var TURN(1,2); var FLAG[1],FLAG[2]:boolean begin FLAG[1]=false; FLAG[2]=false; parbegin process_one; process_two; parend end Edited by Hongjie Dai 12 of 19 procedure process_one begin while true do begin FLAG[1]=true; TRUE=2; while(FLAG[2]and(TURN=2) do no_op C.S. FLAG[1]=false; R.S. end end procedure process_two begin while true do begin FLAG[2]=true; TRUE=1; while(FLAG[1]and(TURN=1) do no_op C.S. FLAG[2]=false; R.S. end end 【考型 1.2】race condition 數個行程同時存取和處理相同資料的情況,而且執行的結果取決於存取時的順序,這種情形稱為競爭情 況。為了避免競爭情況,必須確定一次只能有一個行程來處理某個變數,也就是需要某種形式的 synchronized,這種狀況在作業系統中的不同部分處理資源時經常發生。 【考型 1.2.1】race condition 定義 一組同時執行的行程且共享記憶體情況下,這些合作行程的執行結果會因為行程執行的順序不同而有不 同的結果,稱為競賽情況。可利用 C.S. 設計達到對共用變數的 mutual exclusion 控制即可避免。 【考型 1.3】inter-process-communication 簡稱 IPC,允許行程互相溝通和佊此同步的功能而不需共用相同的位址空間。IPC 在不同電腦間以網路 聯結通訊行程的分散式環境中特別有用。 【考型 1.3.1】行程間溝通的實作方法 1. shared-memory: I. II. algorithm solution Test-and-set、SWAP 等硬體指令支援 2. III. Semaphore IV. Critical region V. Monitor message passing:利用 send 和 receive 指令。例如在 producer and consumer 問題中,兩者的 communication 如下: Producer Consumer PRODUCT ITEM; … Send(receiver, item); Receive( producer, item); … CONSUME ITEM … … 同步的控制可由 link queue capacity 決定,例如 zero capacity 表示 rendezvous 在 Ada。 【考型 1.3.2】為何 Ada rendezvous 保證 task synchronization 和 mutual exclusion synchronization:在 message passing,若 link capacity 的長度為 0,則 sender 必須等待 receiver 收 完資料後,才能繼續傳送下一個資料,所以滿足 synchronization mutual exclusion 當 receiver 還未收到資料時 必須 wait 不能進入 C.S. 當 sender 在未收到 reply : , , ; from receiver 時,無法選出 next data,所以需等候無法立刻進入 C.S.。所以滿足 mutual exclusion Edited by Hongjie Dai 13 of 19 【考型 1.3.3】列出四個利用共用變數解決同步問題的方法 1. 使用 HW instruction。例如 Test-and-set 2. semaphore 3. monitor 4. critical region 【考型 1.3.4】列出三種利用訊息傳遞解決同步問題的方法 1. direct message passing(symmetric) 2. direct message passing(asymmetric) 3. indirect message passing 【考型 1.3.5】為何不用記憶體共享的方式來解決分散式系統同步的問題 因為分散式系統沒有共用記憶體空間,在多個處理器之間也無法利用禁用中斷的方式。 【考型 1.4】The Readers/Writers Problem 只讀出資料的執行緒稱為 Reader,而其餘的稱為 Writer。若有一個寫入者和其它的執行緒(包括寫入 或讀取者)同時存取共用的資料庫時,可能會產生問題。為了確保這類錯誤不會發生,需要這些寫入者 一次只有一個可以存取共用資料庫,而這項要求就是所謂的讀取者∕寫入者問題。滿足: 檔案是可以共享讀取,亦即多個處理元均能同時讀取檔案內容 檔案是寫入互斥,亦即某個處理元正在寫入檔案時,其他處理元不能同時寫入;若有一個處理元正 在寫入檔案,其他處理元亦不能同時讀取此檔案 有兩種類型的讀取者∕寫入者問題: 1. 第一種讀取者∕寫入者問題:除非有一個寫入者已獲得允許去使用這共用資料庫,否則讀取者不需 保持等待狀態;讀取者不需等待其它的讀取者結束,而寫入者需等待 2. 第二種讀取者∕寫入者問題:只要一個寫入者預備好後,需儘快的使其能撰寫共用資料;若有一寫 入者等候存取此資料庫,則不可加入新的讀取者去讀取資料 上面兩種問題的解答都會產生 starvation。在第一種狀況下,寫入者可能會飢餓;在第二種狀態下,讀 取者可能會飢餓。Solaris 2 中讀取者∕寫入者的鎖被用來保護經常存取的資料,通常只能以唯讀的方式 存取。在這種情況下,讀取者∕寫入者鎖會比 semaphore 更有效率,因為多個執行緒可以同時讀取資料, 而號誌只允許逐一地存取資料。讀取者∕寫入者的鎖在製作上比較昂貴,所以只用在長區段的程式碼。 【考型 1.4.1】利用 monitor 來撰寫 second reader-writer problem type read-writer = monitor var v : record; var n_readers, n_writers : integer; var busy : boolean; procedure entry open-read begin await(nwriters = 0); nreaders = nreaders + 1; end; procedure entry open-write begin nwriters = nwriters + 1; await((not Busy) and (nreaders = 0)); busy = true; end; Edited by Hongjie Dai procedure entry close-read begin nreaders = nreaders - 1; end; procedure entry close-write begin nwriters = nwriters - 1; busy = false; end; 14 of 19 begin busy = false; nreaders = 0; nwriters = 0; end 【考型 1.4.2】利用 monitor type 和 condition variable 來撰寫 second reader-writer problem type read-writer = monitor var n_readers, n_writers : integer; var busy : Boolean; var x, y : condition; procedure entry open-read begin region v do begin if nwriters <> 0 then x.wait; nreaders = nreaders + 1; end; end procedure entry close-read begin region v do begin nreaders = nreaders - 1; if nreaders = 0 then y.signal; end; procedure entry open-write begin region v do begin nwriters = nwriters + 1; if ( nreaders <> 0 ) then y.wait; else if ( busy = true)then y.wait; busy = true; end; end procedure entry close-write begin region v do begin nwriters = nwriters - 1; if ( nwriters <> 0 ) then y.signal; else begin busy = false; x.signal; end end; end begin busy = false; nreaders = 0; nwriters = 0; end 【考型 1.5】The Dining-Philosophers Problem 五個哲學家的生活用於思考與吃飯。這些哲學家共用一張有五張椅子的圓桌,每個哲學家各有一張椅 子,這張桌子除了中央有一盒米飯之外,還擺了五支筷子。當哲學家飢餓時,就試圖去使用最靠近他的 筷子(這些筷子介於他和同僚之間) ;哲學家每次只能使用一雙筷子吃飯,不能夠使用他的鄰居正在用 的筷子。一個飢餓的哲學家同時可使用他的兩支筷子吃飯,而不需放下其中任何一支筷子。吃完飯後, 放下筷子繼續思考。這個問題有一個簡單的解決方式就是用一個 semaphores 表示一支筷子。若哲學家 欲拾取一支筷子相當於執行這個號誌的 P 運算;放下一支筷子就執行這號誌的 V 運算。因此共用的資 料為: Edited by Hongjie Dai 15 of 19 Semaphore chopstick [ ] = new Semaphore[5]; 其中的 chopStick 的每一元素初值為 1,哲學家 i 的結構: while(true){ // 抓左邊的筷子 chopStick[i].P(); // 抓右邊的筷子 chopStick[(i+1)%5].P(); eating(); // 放下左邊的筷子 chopStick[i].V(); // 放下右邊的筷子 chopStick[(i+1)%5].V(); thinking(); } 雖然這解答保證沒有兩個相鄰的哲學家可同時吃飯,但是它可能產生死結。假設五個哲學家同時感覺到 飢餓,且每個人想時取它們左邊的一支筷子,則此時 chopStick 的每個元素都是 0,而當一個哲學家 想使用他右邊的筷子時將永遠延遲。補救方法如下: 至多允許四個哲學家可同時坐在此桌旁 允許哲學家只有在他左右兩支筷子均為可用時,才可拾取(可能引起 The Critical Section Problem) 使用一不對稱的解決方法:座次為奇數的哲學家先使用其左邊的筷子,然後再使用其右邊的筷子; 而座次為偶數的哲學家先使用其右邊的筷子,再使用其左邊的筷子 【考型 1.5.1】利用 monitor 解決 dining-philosophers 問題 type dining-ph=monitor var state:array[0…4] of (thinking, hungry, eating); var self:array[0…4] of condition procedure entry pickup(i:0..4) begin state [i]=hungry; test(i); if state [i] != eating then self[i].wait end procedure test(k:0..4) end // 測試左右鄰居有沒在吃飯 procedure entry put_down(i:0…4) begin state [i]=thinking; test((i+4)mod5); test((i+1)mod5); begin if state[(k+4)mod5]!=eating and state[k]=hungry and state[(k+1)mod5!=eating // (k+4)mod5 為左鄰;(k+1)mod5 為右鄰 then begin state [k]=eating; self[k].signal; end end begin for i=0 to 4 do Edited by Hongjie Dai 16 of 19 state [i]=thinking; end 【考型 1.6】Producer-Consumer Example 這個問題是 Cooperating process 常見的範例。解題的方法有: 1. 利用緩衝區(bounded buffer 或是 unbounded buffer) : I. bounded buffer:緩衝區可能由作業系統經由簡單使用 IPC 提供,或是由程式設計者在寫程式 時利用共用記憶體來提供。利用共用記憶體來解答有限緩衝區會面臨兩個問題,首先如果緩衝 區滿了或是全空了,則生產者和消費者都使用 busy waiting。第二,對於生產者和消費者共用 的變數 count 會發生 race condition。 II. unbounded buffer:無限緩衝區的生產者-消費者問題是假設緩衝區的大小沒有限制,生產者可 以不斷地產生新的欄位,消費者可能必須等待或是不用。 2. 使用訊息傳遞來解決:譬如共用 port、控制獨立的 thread 【考型 1.6.1】利用 critical region 解決 producers-consumer problem The buffer space and its pointers are defined in struct buffer{ item pool [n]; int count,in,out; } Producer 程序如下: region buffer when(count<n){ pool[in]=next p; in=(in+1)%n; count++; } Consumer 程序如下: region buffer when (count>0){ next c=pool[out]; out=(out+1)%n; count--; } 【考型 1.7】transaction transaction 等待被執行,每執行完一個處理元之後,再依序處理下一個處理元,這種執行方式稱為循序 執行。多個處理元依循序執行方式執行,結果是對的,假如有 n 個處理元,則有 n! 種循序執行次序。 循序執行違反分時系統之初衷。 可循序化的排程(Serializable Schedule) 處理元不是依循序執行,而是依中央處理器排程次序執行,其 : 結果與循序執行相同,則此執行次序是可 Serializable 的。 Conflict Serializable:If a schedule S can be transformed into a serial schedule S’ by a series of swaps of non-conflicting operations, we say that a schedule S is conflict serializable. 【考型 1.7.1】Two-phase locking protocol 【考型 1.7.1.2】敘述 Two-phase locking protocol(交大) 確保 transaction 可以 serializability 的一種方法。為每個資源項加上一個 lock,並要求每筆交易遵循 locking protocol。Two-phase locking protocol 要求每一筆 transaction 以兩種相位發出上鎖和解鎖要求: 1. Growing phase:一筆 transaction 可以獲得鎖,但不能釋放任何鎖 2. Shrinking phase:一筆交易可以釋放鎖,但不能獲得任何新鎖 一開始,transaction 是在 growing phase,依照需求取得 lock 之後,一但此交易釋放出一個 lock,它就 進入 shrinking phase 並且不能獲得任何新鎖。其可以確保 conflict serializable property,但不能保證 deadlock free。 Edited by Hongjie Dai 17 of 19 【考型 2】priority inversion 高優先權必須等待低優先權的行程完成的特殊狀態,通常發生在同步的機制裡。為了降低分派的潛伏 期,有一種方式是讓整個核心成為可搶先,為了確保正確的操作,所有的核心資料結構都必須使用同步 機制加以保護。使用這種方法可以保證核心永遠可以被搶先,因為任何核心正在更新的資料都被保護以 防止被高優先權的行程修改。但是如果高優先權的行程需要讀或修改核心中被另一個低優先權的行程使 用到資料時,就會發生 priority inversion。事實上可能有許多的行程都在使用高優先權行程所需的資源, 此時可用 priority inheritance protocol 來解決。也就是當有一系列的行程都在使用高優先權行程所需的 資源時,藉著優先權繼承規約方法下,所有行程繼承高優先權直到它們用完這個爭議的資源。 【考型 2.1】什麼情形下可能造成高優先權的行程等候低優先權的行程完成工作(清大) 1. non-preemptive scheduling algorithm 可能發生此一現象。解決的辦法是改用 preemptive 策略即可。 若考慮防止 starvation,可用 aging technique 2. priority inversion 也會發生此現象,可用 priority inheritance protocol 解決 3. wait-die strategy in distribution system,若 Pi 等待 Pj 佔用的某個資源,若 Pi 的 priority 較大,則 允許 Pi 等待。若 Pi 的 priority 較小,則 Pi rollback,不能等待 Pj。可能的問題是 starvation,可 利用 time-stamp ordering;time stamp 小,則優先權較大,來防止 starvation 【考型 3】program relocation 定義 當程式執行起始位址改變時,則 object code 中某些內容需跟著調整,避免資料存取錯誤的修正動作稱 為 program relocation。例如採用 direct addressing mode 的指令需作 relocation 修正,通常由 linking loader 於 loading time 完成。 【考型 4】OSI network model 【考型 4.1】OSI 模式的 7 層架構(7 Layer) 根據 OSI 通訊協定可以分成 7 個階層: 1. 實體層(Physical Layer) :實體層是定義電學的技術(何種頻率傳送等)或連端子的形狀、端子所 付 pin 陣列等。 2. 資料連結層(Data Link Layer) :資料連結層是規定在纜線所連結裝置上存取的協定。資料連結層以 理論的方式去定義如何進行資料的傳送。對應錯誤情況等方式也屬於此層的協定。 3. 網路層(Network Layer) :屬於網路層的協定,其中規定了選擇數個通訊路徑(網路)的方法。 4. 傳輸層(Transport Layer) :在傳輸層中執行 1、2、3 層錯誤的對應。 5. 交談層(Session Layer) :交談層的協定是決定主機要如何進行通訊的協定。相當於決定和對方間所 使用的語言。 6. 表現層(Presentation Layer) OSI 的第 6 層,和字面的意思相同。也就是規定資訊表現的格式時所 : 使用的協定。 7. 應用層(Application Layer) :應用層則是規定在應用程式的程式裡如何進行資訊通訊。像是整個電 腦通訊或 WWW 瀏覽器的操作就是屬於此層的協定。也是最後使用者所會實際用到的協定。 Edited by Hongjie Dai 18 of 19 Edited by Hongjie Dai 19 of 19 ...
View Full Document

This note was uploaded on 12/29/2009 for the course INFO ENGI 9801 taught by Professor Wu during the Spring '09 term at 東京国際大学.

Ask a homework question - tutors are online