Download presentation
Presentation is loading. Please wait.
Published byDerek Bryan Modified over 9 years ago
1
Chapter 6: Synchronization 籃玉如
2
Part Three: Process Coordination Chapter 6 Synchronization Chapter 7 Deadlocks 2
3
Chapter 6: Synchronization 6.1 Background 6.2 The Critical-Section Problem 6.3 Peterson’s Solution 6.4 Synchronization Hardware 6.5 Semaphores 6.6 Classic Problems of Synchronization 6.7 Monitors 6.8 Synchronization Examples 6.9 Atomic Transactions (X) 3
4
6.1 Background Concurrent access to shared data may result in data inconsistency Maintaining data consistency requires mechanisms to ensure the orderly execution of cooperating processes Suppose that we wanted to provide a solution to the consumer-producer problem that fills all the buffers. We can do so by having an integer count that keeps track of the number of full buffers. Initially, count is set to 0. It is incremented by the producer after it produces a new buffer and is decremented by the consumer after it consumes a buffer. 4
5
Producer while (true) { /* produce an item and put in nextProduced while (count == BUFFER_SIZE) ; // do nothing buffer [in] = nextProduced; in = (in + 1) % BUFFER_SIZE; count++; } while (true) { while (count == 0) ; // do nothing nextConsumed = buffer[out]; out = (out + 1) % BUFFER_SIZE; count--; /* consume the item in nextConsumed } Consumer 5
6
Race Condition count++ could be implemented as (in machine language) register1 = count register1 = register1 + 1 count = register1 count-- could be implemented as register2 = count register2 = register2 - 1 count = register2 Consider this execution interleaving with “count = 5” initially: S0: producer execute register1 = count {register1 = 5} S1: producer execute register1 = register1 + 1 {register1 = 6} S2: consumer execute register2 = count {register2 = 5} S3: consumer execute register2 = register2 - 1 {register2 = 4} S4: producer execute count = register1 {count = 6 } S5: consumer execute count = register2 {count = 4} 6
7
6.2 The Critical-Section Problem A system 包括 n 個 processes {p 0, p 1, …, p n-1 }. 每一個 process 擁有一段程 式片段 (the segment of code is called a critical section) , in this segment 這個 process 可以改變共同變數 (common variables) ,更新表格 ,寫入一的檔案等。 這樣系統的一個重要特性是當有一個 process 再這段 critical section 執行 某些運算時,其他的 processes 就不被允許對此 critical section 進行任何 運算動作。 此稱為 The critical section problem ,它的設計主要的目的是作為 cooperating processes 之間的 protocol do { entry section critical section exit section remainder section } while (TRUE); 7
8
Solution to Critical-Section Problem 要解決 the critical-section problem 必須滿足 3 個要求: 1.Mutual Exclusion – 如果 process pi 正在執行它的 CS ,則其他 之 processes 不得執行它們自己的 CS 。 2. Progress – 又稱為 lockstep synchronization ,沒有 process 正在執 行 CS ,則欲進入 CS5 之 processes ( 非在 remainder section) 可以 被 select 。 3. Bounded Waiting – 一個 已發出 request 之 process 經過一段時 間 (bound) 應該會被 grant 。 8
9
6.3 Peterson’s Solution (Software Solution) A classic software-based solution to the critical-section problem 解決兩個 processes 輪流在他們的 critical sections & remainder sections 執行的問題 Assume that the LOAD and STORE instructions are atomic; that is, cannot be interrupted. The two processes share two variables: int turn; Boolean flag[2] The variable turn indicates whose turn it is to enter the critical section. The flag array is used to indicate if a process is ready to enter the critical section. flag[i] = true implies that process P i is ready! 9
10
Algorithm for Process P i do { flag[i] = TRUE; turn = j; while ( flag[j] && turn == j); CRITICAL SECTION flag[i] = FALSE; REMAINDER SECTION } while (TRUE); 10
11
6.4 Synchronization Hardware (Hardware Solution) 硬體上的特殊性質可以使寫程式的工作變得比較容易,並且增進 系統的效率。 Uniprocessors – could disable interrupts (i.e., 正在執行的 critical- section modifying 不能被中斷 ) to solve critical-section problem Currently running code would execute without preemption Generally too inefficient on multiprocessor systems 因為這個訊息必須傳給所有的 processors ,此具相當浪費 時間,使的系統效能大為降低 Modern machines provide special atomic hardware instructions ,亦即可在一個 memory cycle 內完成,不可被切割 Atomic = non-interruptable Test-and-set 與 swap 指令都是 indivisible ,即 executed atomically 於 1 個 memory cycle 。 11
12
Algorithm 1: TestAndndSet Instruction Definition: boolean TestAndSet (boolean *target) { boolean rv = *target; *target = TRUE; return rv: } 12
13
Shared boolean variable lock., initialized to false. Solution: do { while ( TestAndSet (&lock )) ; /* do nothing // critical section lock = FALSE; // remainder section } while ( TRUE); Solution using TestAndSet 13
14
Algorithm 2: Swap Instruction Definition: void Swap (boolean *a, boolean *b) { boolean temp = *a; *a = *b; *b = temp: } 14
15
Solution using Swap Shared Boolean variable lock initialized to FALSE; Each process has a local Boolean variable key. Solution: do { key = TRUE; while ( key == TRUE) Swap (&lock, &key ); // critical section lock = FALSE; // remainder section } while ( TRUE); 15
16
Algorithm 3: Burn’s Algorithm Bounding-waiting mutual exclusion with TestAndSet () Satisfies all the critical-section requirements The common data structures are Waiting [n] and lock, both are initialized to false. Boolean Waiting [n]; Boolean lock; 16
17
Burn’s Algorithm do { waiting [i] = TRUE; key = TRUE; while ( waiting [i] && key ) key = TestAndSet (&lock); waiting [i] = FALSE; // critical section j = ( I + 1 ) % n; while (( j != i) && ! waiting [j] ) j = ( j+1 ) % n; if ( j == i ) lock = FALSE; else waiting [j] = FALSE; // remainder section } while (TRUE); 17
18
6.5 Semaphore 由於 software & hardware solutions 很難應用到複雜的問題, 為了解決這個問題,可以使用 semaphore (a synchronization tool) 。 對應用程式設計者而言不像 software & hardware solutions 複 雜 Synchronization tool that does not require busy waiting Semaphore S – integer variable Can only be accessed via two indivisible (atomic) operations: S: wait() and signal() Originally called P() and V() 18
19
6.5 Semaphore wait (S) { while S <= 0 ; // no-op S--; } signal (S) { S++; } 19
20
Semaphore as General Synchronization Tool Counting semaphore – integer value can range over an unrestricted domain Binary semaphore – integer value can range only between 0 and 1; can be simpler to implement Also known as mutex locks Can implement a counting semaphore S as a binary semaphore to deal with the critical-section problem for n processes Provides mutual exclusion Semaphore S; // initialized to 1 wait (S); Critical Section signal (S); 20 signal (S) { S++; }
21
Usage of Semaphore Counting semaphore 可用在資源的管控上: S is initialized to n 每一個需要使用 resource 的 process 執行 wait () 當一個 resource 被 release 時,執行 signal () 當 S=0 時,則需要使用 resource 的 processes 就必須等待 Semaphore 也用來處理不同的同步問題,例如有兩個同步的 processes , P1 要執行 S1 指令,而 P2 要執行 S2 指令,但是 S2 得在 S1 之後才能執行。 方法: p1 & P2 共享一個 semaphore synch (initial synach =0) 在 P1 加入 S1; signal (); 在 P2 加入 wait (synch); S2; 21
22
Semaphore Implementation Must guarantee that no two processes can execute wait () and signal () on the same semaphore at the same time Thus, implementation becomes the critical section problem where the wait and signal code are placed in the critical section. Could now have busy waiting in critical section implementation But implementation code is short Little busy waiting if critical section rarely occupied Note that applications may spend lots of time in critical sections and therefore this is not a good solution. 22
23
Semaphore Implementation with no Busy waiting With each semaphore there is an associated waiting queue. Each entry in a waiting queue has two data items: value (of type integer) pointer to next record in the list Two operations: block – place the process invoking the operation on the appropriate waiting queue. wakeup – remove one of processes in the waiting queue and place it in the ready queue. 23
24
Semaphore Implementation with no Busy waiting (Cont.) Implementation of wait: wait (S){ value--; if (value < 0) { add this process to waiting queue block(); } } Implementation of signal: Signal (S){ value++; if (value <= 0) { remove a process P from the waiting queue wakeup(P); } } 24
25
Deadlock and Starvation Deadlock – two or more processes are waiting indefinitely for an event that can be caused by only one of the waiting processes 互相在等對方發出 signal () Let S and Q be two semaphores initialized to 1 P 0 P 1 wait (S); wait (Q); wait (Q); wait (S);.. signal (S); signal (Q); signal (Q); signal (S); Starvation – indefinite blocking. A process may never be removed from the semaphore queue in which it is suspended. 25
26
6.6 Classical Problems of Synchronization These problems are used for testing nearly every newly proposed synchronization scheme. Bounded-Buffer Problem Readers and Writers Problem Dining-Philosophers Problem 26
27
Bounded-Buffer Problem N buffers, each can hold one item Semaphore mutex initialized to the value 1 Semaphore full initialized to the value 0 Semaphore empty initialized to the value N. 27
28
Bounded Buffer Problem (Cont.) The structure of the producer process do { // produce an item wait (empty); wait (mutex); // add the item to the buffer signal (mutex); signal (full); } while (true); 28
29
Bounded Buffer Problem (Cont.) The structure of the consumer process do { wait (full); wait (mutex); // remove an item from buffer signal (mutex); signal (empty); // consume the removed item } while (true); 29
30
Readers-Writers Problem A data set is shared among a number of concurrent processes Readers – only read the data set; they do not perform any updates Writers – can both read and write. Problem – allow multiple readers to read at the same time. Only one single writer can access the shared data at the same time. 30
31
Readers-Writers Problem Shared Data Data set Semaphore mutex initialized to 1. Semaphore wrt initialized to 1. Integer readcount initialized to 0. 31
32
Readers-Writers Problem (Cont.) The structure of a writer process do { wait (wrt) ; // writing is performed signal (wrt) ; } while (true) 32
33
Readers-Writers Problem (Cont.) The structure of a reader process do { wait (mutex) ; readcount ++ ; if (readercount == 1) wait (wrt) ; signal (mutex) // reading is performed wait (mutex) ; readcount - - ; if redacount == 0) signal (wrt) ; signal (mutex) ; } while (true) 33
34
Dining-Philosophers Problem Shared data Bowl of rice (data set) Semaphore chopstick [5] initialized to 1 34
35
Dining-Philosophers Problem (Cont.) The structure of Philosopher i: Do { wait ( chopstick[i] ); wait ( chopStick[ (i + 1) % 5] ); // eat signal ( chopstick[i] ); signal (chopstick[ (i + 1) % 5] ); // think } while (true) ; 35
36
Problems with Semaphores Incorrect use of semaphore operations: signal (mutex) …. wait (mutex) wait (mutex) … wait (mutex) Omitting of wait (mutex) or signal (mutex) (or both) 36
37
6.7 Monitors A high-level abstraction that provides a convenient and effective mechanism for process synchronization 包括 data 以及 procedures Only one process may be active within the monitor at a time 37
38
6.7 Monitors monitor monitor-name { // shared variable declarations procedure P1 (…) { …. } … procedure Pn (…) {……} Initialization code ( ….) { … } … } 38 Fig. 6.18 Syntax of a monitor
39
Schematic view of a Monitor 39
40
Monitors Monitor 結構可確保在一個時間點只有一個 process 在 monitor 中執行。 40 Fig. 6.19 Schematic view of a monitor
41
Monitors 雖然 programmer 不需要明確的寫 synchronization constraint 的程式碼,但仍需定義 additional synchronization mechanisms 。 This mechanisms are provided by the condition construct. 41
42
Monitors condition x, y; Two operations on a condition variable: x.wait () – a process that invokes the operation is suspended. x.signal () – resumes one of processes (if any) tha invoked x.wait () 如果沒有 process 在 suspend 則 signal operation 沒有 任何動作 ( 與 P / V 不同, V 每次都會影響 semaphore) 42
43
Monitor with Condition Variables Monitor with Condition Variables 43 Fig. 6.20
44
Monitors 如果 process P 引發 x.signal () 時,正有一個 process Q 是在等 x condition ,則有以下兩種情形: Signal and wait. P either waits until Q leaves the monitor or waits for another condition. Signal and continue. Q either waits until P leaves the monitor or waits for another condition. 44
45
6.7.2 Solution to Dining Philosophers monitor DP { enum { THINKING; HUNGRY, EATING) state [5] ; condition self [5]; void pickup (int i) { state[i] = HUNGRY; test(i); if (state[i] != EATING) self [i].wait; } void putdown (int i) { state[i] = THINKING; // test left and right neighbors test((i + 4) % 5); test((i + 1) % 5); } 45
46
Solution to Dining Philosophers (cont) void test (int i) { if ( (state[(i + 4) % 5] != EATING) && (state[i] == HUNGRY) && (state[(i + 1) % 5] != EATING) ) { state[i] = EATING ; self[i].signal () ; } initialization_code() { for (int i = 0; i < 5; i++) state[i] = THINKING; } 46
47
6.7.3 Implementing a Monitor Using Semaphores 對每一個 monitor 提一個 semaphore: mutex (initialized to 1) 。每一個行程在進入 monitor 之前,都必須先執行 wait (mutex) 的動作,並在離開 monitor 之後,執行 signal (mutex) 的動作。 因為一個 signaling process 可能必須等待,直到 the resumed process 離開 monitor 或是等待,所以增加一個 semaphore: next (initialized to 0). The signaling processes may suspend themselves on next semaphore. next_count: an integer variable To count the number of processes suspended on next 47
48
6.7.3 Implementing a Monitor Using Semaphores Each external procedure F: wait (mutex); … body of F … if (next_count > 0) signal (next); else signal (mutex); 48
49
6.7.3 Implementing a Monitor Using Semaphores Condition x: semaphore x_sem (initialized to 0) x_count (an integer, initialized to 0) 49
50
6.7.4 Resuming Processes Within a Monitor 可能有以下問題,在 Chap 17 System Protection 再討論 一個 process 可能在沒有先取得某項資源的 存取允許權之前就先使用該資源。 一個 process 在獲得某項資源的存取權之後 ,就佔住不放。 一個 process 可能會試圖釋放一項從未取得 過的資源。 一個 process 可能會對相同的資源提出兩次 要求 ( 沒有先釋放出該資源 ) 。 50
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.