Chapter 6: Synchronization 籃玉如. Part Three: Process Coordination Chapter 6 Synchronization...

Preview:

Citation preview

Chapter 6: SynchronizationChapter 6: Synchronization

籃玉如籃玉如

Part Three: Process CoordinationPart Three: Process Coordination

Chapter 6 Synchronization

Chapter 7 Deadlocks

2

Chapter 6: SynchronizationChapter 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

6.1 Background6.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

Producer 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

}

ConsumerConsumer

5

Race ConditionRace 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

6.2 The Critical-Section Problem6.2 The Critical-Section Problem

A system 包括 n 個 processes {p0, p1, …, pn-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

Solution to Critical-Section ProblemSolution 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

6.3 Peterson’s Solution (Software Solution)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 Pi is ready!

9

Algorithm for Process Algorithm for Process PPii

do {

flag[i] = TRUE;

turn = j;

while ( flag[j] && turn == j);

CRITICAL SECTION

flag[i] = FALSE;

REMAINDER SECTION

} while (TRUE);

10

6.4 Synchronization Hardware 6.4 Synchronization Hardware (Hardware Solution)(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

Algorithm 1: TestAndndSet Instruction Algorithm 1: TestAndndSet Instruction

Definition:

boolean TestAndSet (boolean *target)

{

boolean rv = *target;

*target = TRUE;

return rv:

}

12

Shared boolean variable lock., initialized to false. Solution:

do {

while ( TestAndSet (&lock ))

; /* do nothing

// critical section

lock = FALSE;

// remainder section

} while ( TRUE);

Solution using TestAndSetSolution using TestAndSet

13

Algorithm 2: Swap InstructionAlgorithm 2: Swap Instruction

Definition:

void Swap (boolean *a, boolean *b)

{

boolean temp = *a;

*a = *b;

*b = temp:

}

14

Solution using SwapSolution 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

Algorithm 3: Burn’s AlgorithmAlgorithm 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

Burn’s AlgorithmBurn’s Algorithmdo {

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

6.5 Semaphore6.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

6.5 Semaphore6.5 Semaphore

wait (S) {

while S <= 0

; // no-op

S--;

}

signal (S) {

S++;

}

19

Semaphore as General Synchronization ToolSemaphore 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++; }

Usage of SemaphoreUsage 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

Semaphore ImplementationSemaphore 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

Semaphore Implementation with no Busy waitingSemaphore 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

Semaphore Implementation with no Busy waitingSemaphore Implementation with no Busy waiting (Cont.)(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

Deadlock and StarvationDeadlock 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

P0 P1

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

6.6 Classical Problems of Synchronization6.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

Bounded-Buffer ProblemBounded-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

Bounded Buffer Problem (Cont.)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

Bounded Buffer Problem (Cont.)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

Readers-Writers ProblemReaders-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

Readers-Writers ProblemReaders-Writers Problem

Shared Data

Data set

Semaphore mutex initialized to 1.

Semaphore wrt initialized to 1.

Integer readcount initialized to 0.

31

Readers-Writers Problem (Cont.)Readers-Writers Problem (Cont.)

The structure of a writer process

do {

wait (wrt) ;

// writing is performed

signal (wrt) ;

} while (true)

32

Readers-Writers Problem (Cont.)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

Dining-Philosophers ProblemDining-Philosophers Problem

Shared data

Bowl of rice (data set)

Semaphore chopstick [5] initialized to 1

34

Dining-Philosophers Problem (Cont.)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

Problems with SemaphoresProblems 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

6.7 Monitors6.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

6.7 Monitors6.7 Monitors

monitor monitor-name

{

// shared variable declarations

procedure P1 (…) { …. }

procedure Pn (…) {……}

Initialization code ( ….) { … }

}

}

38

Fig. 6.18 Syntax of a monitor

Schematic view of a MonitorSchematic view of a Monitor

39

MonitorsMonitors

Monitor 結構可確保在一個時間點只有一個 process在 monitor 中執行。

40Fig. 6.19 Schematic view of a monitor

MonitorsMonitors

雖然 programmer 不需要明確的寫 synchronization constraint 的程式碼,但仍需定義 additional synchronization mechanisms 。 This mechanisms are provided by the

condition construct.

41

MonitorsMonitors

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

Monitor with Condition VariablesMonitor with Condition Variables

43Fig. 6.20

MonitorsMonitors

如果 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

6.7.2 Solution to Dining Philosophers6.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

Solution to Dining Philosophers (cont)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

6.7.3 Implementing a Monitor Using Semaphores6.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

6.7.3 Implementing a Monitor Using Semaphores6.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

6.7.3 Implementing a Monitor Using Semaphores6.7.3 Implementing a Monitor Using Semaphores

Condition x:

semaphore x_sem (initialized to 0)

x_count (an integer, initialized to 0)

49

6.7.4 Resuming Processes Within a Monitor6.7.4 Resuming Processes Within a Monitor

可能有以下問題,在 Chap 17 System Protection 再討論 一個 process 可能在沒有先取得某項資源的

存取允許權之前就先使用該資源。 一個 process 在獲得某項資源的存取權之後

,就佔住不放。 一個 process 可能會試圖釋放一項從未取得

過的資源。 一個 process 可能會對相同的資源提出兩次

要求 ( 沒有先釋放出該資源 ) 。50

Recommended