Presentation is loading. Please wait.

Presentation is loading. Please wait.

Silberschatz, Galvin and Gagne ©2007 Operating System Concepts with Java – 7 th Edition, Nov 15, 2006 Chapter 6 (a): Synchronization.

Similar presentations


Presentation on theme: "Silberschatz, Galvin and Gagne ©2007 Operating System Concepts with Java – 7 th Edition, Nov 15, 2006 Chapter 6 (a): Synchronization."— Presentation transcript:

1 Silberschatz, Galvin and Gagne ©2007 Operating System Concepts with Java – 7 th Edition, Nov 15, 2006 Chapter 6 (a): Synchronization

2 6.2 Silberschatz, Galvin and Gagne ©2007 Operating System Concepts with Java – 7 th Edition, Nov 15, 2006 Module 6: Process Synchronization  Background  Producer/Consumer Again  Race Conditions  Scheduler Assumptions  The Critical-Section Problem  Critical Section Goals  Deriving a Solution  Peterson’s Algorithm  Bakery Algorithm  Hardware Support

3 6.3 Silberschatz, Galvin and Gagne ©2007 Operating System Concepts with Java – 7 th Edition, Nov 15, 2006 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. Have an integer count that tracks the number of full buffers. Initially, count is set to 0. Producer increments count after producing a buffer Consumer decrements after consuming a buffer

4 6.4 Silberschatz, Galvin and Gagne ©2007 Operating System Concepts with Java – 7 th Edition, Nov 15, 2006 Producer-Consumer Producer while (true) { /* produce an item and */ /* put in nextProduced */ while (count == BUFFER_SIZE) ; // do nothing b/c full buffer [in] = nextProduced; in = (in + 1) % BUFFER_SIZE; count++; } Consumer while (true) { while (count == 0) ; // do nothing b/c empty nextConsumed = buffer[out]; out = (out + 1) % BUFFER_SIZE; count--; /* consume the item */ /* in nextConsumed */ }

5 6.5 Silberschatz, Galvin and Gagne ©2007 Operating System Concepts with Java – 7 th Edition, Nov 15, 2006 Race Condition  count++ could be implemented as 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.6 Silberschatz, Galvin and Gagne ©2007 Operating System Concepts with Java – 7 th Edition, Nov 15, 2006 What happened?  Threads (and sometimes processes) share global memory  When a process contains multiple threads, they have Private registers and stack memory (the context switching mechanism needs to save and restore registers when switching from thread to thread) Shared access to the remainder of the process “state”  This can result in race conditions

7 6.7 Silberschatz, Galvin and Gagne ©2007 Operating System Concepts with Java – 7 th Edition, Nov 15, 2006 Two threads, one counter Popular web server  Uses multiple threads to speed things up.  Simple shared state error: each thread increments a shared counter to track number of hits  What happens when two threads execute concurrently? … hits = hits + 1; …

8 6.8 Silberschatz, Galvin and Gagne ©2007 Operating System Concepts with Java – 7 th Edition, Nov 15, 2006 Shared counters  Possible result: lost update!  One other possible result: everything works.  Difficult to debug  Called a “race condition” hits = read hits (0) hits = read hits (0) T1 T2 hits = 1 hits = 0 time

9 6.9 Silberschatz, Galvin and Gagne ©2007 Operating System Concepts with Java – 7 th Edition, Nov 15, 2006 Race conditions  Def: a timing dependent error involving shared state Whether it happens depends on how threads scheduled In effect, once thread A starts doing something, it needs to “race” to finish it because if thread B looks at the shared memory region before A is done, it may see something inconsistent  Hard to detect: All possible schedules (permutations) have to be safe  Number of possible schedule permutations is huge  Some bad schedules? Some that will work sometimes? Intermittent  Unpredictable  Timing dependent = small changes can hide bug If a bug is deterministic and repeatable, celebrate!

10 6.10 Silberschatz, Galvin and Gagne ©2007 Operating System Concepts with Java – 7 th Edition, Nov 15, 2006 If i is shared, and initialized to 0 Who wins? Is it guaranteed that someone wins? What if each thread runs on a separate, identical speed CPU?  executing in parallel Scheduler Assumptions Process b: while(i > -10) i = i - 1; print “B won!”; Process a: while(i < 10) i = i +1; print “A won!”;

11 6.11 Silberschatz, Galvin and Gagne ©2007 Operating System Concepts with Java – 7 th Edition, Nov 15, 2006 Scheduler Assumptions  Normally we assume that A scheduler always gives every executable thread opportunities to run  In effect, each thread makes finite progress But schedulers aren’t always fair  Some threads may get more chances than others To reason about worst case behavior we sometimes think of the scheduler as an adversary trying to “mess up” the algorithm

12 6.12 Silberschatz, Galvin and Gagne ©2007 Operating System Concepts with Java – 7 th Edition, Nov 15, 2006 Critical Section Problem  Problem: Design a protocol for processes to cooperate, such that only one process is in its critical section at any time How to make multiple instructions seem like one? Processes progress with non-zero speed, no assumption on clock speed Used extensively in operating systems: Queues, shared variables, interrupt handlers, etc. Process 1 Process 2 CS 1 Time  CS 2

13 6.13 Silberschatz, Galvin and Gagne ©2007 Operating System Concepts with Java – 7 th Edition, Nov 15, 2006 Critical-Section Problem 1. Race Condition - When there is concurrent access to shared data and the final outcome depends upon order of execution. 2. Critical Section - Section of code where shared data is accessed. 3. Entry Section - Code that requests permission to enter its critical section. 4. Exit Section - Code that is run after exiting the critical section

14 6.14 Silberschatz, Galvin and Gagne ©2007 Operating System Concepts with Java – 7 th Edition, Nov 15, 2006 Critical Section Goals  Threads do some stuff but eventually might try to access shared data CSEnter(); Critical section CSExit(); T1 T2 time CSEnter(); Critical section CSExit(); T1 T2

15 6.15 Silberschatz, Galvin and Gagne ©2007 Operating System Concepts with Java – 7 th Edition, Nov 15, 2006 Critical Section Goals  Perhaps they loop (perhaps not!) T1 T2 CSEnter(); Critical section CSExit(); T1 T2 CSEnter(); Critical section CSExit();

16 6.16 Silberschatz, Galvin and Gagne ©2007 Operating System Concepts with Java – 7 th Edition, Nov 15, 2006  We would like Safety (aka mutual exclusion)  No more than one thread can be in a critical section at any time. Liveness (aka progress)  A thread that is seeking to enter the critical section will eventually succeed Bounded waiting  A bound must exist on the number of times that other threads are allowed to enter their critical sections after a thread has made a request to enter its critical section and before that request is granted  Assume that each process executes at a nonzero speed  No assumption concerning relative speed of the N processes  Ideally we would like fairness as well If two threads are both trying to enter a critical section, they have equal chances of success … in practice, fairness is rarely guaranteed Critical Section Goals

17 6.17 Silberschatz, Galvin and Gagne ©2007 Operating System Concepts with Java – 7 th Edition, Nov 15, 2006 Solving the problem CSEnter() { while(inside) continue; inside = true; }  A first idea: Have a boolean flag, inside. Initially false. CSExit() { inside = false; }  Now ask: Is this Safe? Live? Bounded waiting? Code is not safe: thread 0 could finish the while test when inside is false, but then thread 1 might call CSEnter() before thread 0 can set inside to true!

18 6.18 Silberschatz, Galvin and Gagne ©2007 Operating System Concepts with Java – 7 th Edition, Nov 15, 2006 Solving the problem: Take 2 CSEnter(int i) { inside[i] = true; while(inside[j]) continue; }  A different idea (assumes just two threads): Have a boolean flag, inside[i]. Initially false. CSExit(int i) { inside[i] = false; }  Now ask: Is this Safe? Live? Bounded waiting? Code isn’t live (doesn’t guarantee progress): with bad luck, both threads could be looping, with 0 looking at 1, and 1 looking at 0

19 6.19 Silberschatz, Galvin and Gagne ©2007 Operating System Concepts with Java – 7 th Edition, Nov 15, 2006 Solving the problem: Take 3 CSEnter(int i) { while(turn != i) continue; }  Another broken solution, for two threads Have a turn variable, turn, initially 1. CSExit(int i) { turn = i ^ 1; }  Now ask: Is this Safe? Live? Bounded waiting? Code isn’t live: thread 1 can’t enter unless thread 0 did first, and vice-versa. But perhaps one thread needs to enter many times and the other fewer times, or not at all

20 6.20 Silberschatz, Galvin and Gagne ©2007 Operating System Concepts with Java – 7 th Edition, Nov 15, 2006 Peterson’s Algorithm (1981) CSEnter(int i) { inside[i] = true; turn = J; while(inside[J] && turn == J) continue; } CSExit(int i) { inside[i] = false; }  Now ask: Is this Safe? Live? Bounded waiting?

21 6.21 Silberschatz, Galvin and Gagne ©2007 Operating System Concepts with Java – 7 th Edition, Nov 15, 2006 Peterson’s Solution  Two process solution  Assume that the LOAD and STORE instructions are atomic; that is, cannot be interrupted.  The two processes share two variables: int turn; Boolean inside[2]  The variable turn indicates whose turn it is to enter the critical section.  The inside array is used to indicate if a process is ready to enter the critical section. inside[i] = true implies that process P i is ready!

22 6.22 Silberschatz, Galvin and Gagne ©2007 Operating System Concepts with Java – 7 th Edition, Nov 15, 2006  Safety (by contradiction): Assume that both processes (Alice and Bob) are in their critical section (and thus have their inside flags set). Since only one, say Alice, can have the turn, the other (Bob) must have reached the while() test before Alice set her inside flag. However, after setting his inside flag, Alice gave away the turn to Bob. Bob has already changed the turn and cannot change it again, contradicting our assumption. Liveness & Bounded waiting => the turn variable. Analyzing Peterson’s Algorithm

23 6.23 Silberschatz, Galvin and Gagne ©2007 Operating System Concepts with Java – 7 th Edition, Nov 15, 2006 Generalize to N Threads?  Obvious approach won’t work:  Issue: Who’s turn is next? CSEnter(int i) { inside[i] = true; for(J = 0; J < N; J++) while(inside[J] && turn == J) continue; } CSExit(int i) { inside[i] = false; }

24 6.24 Silberschatz, Galvin and Gagne ©2007 Operating System Concepts with Java – 7 th Edition, Nov 15, 2006 Bakery “concept”  Think of a popular store with a crowded counter, perhaps the cheese line at Zabar’s People take a ticket from a machine If nobody is waiting, tickets don’t matter When several people are waiting, ticket order determines order in which they can make purchases

25 6.25 Silberschatz, Galvin and Gagne ©2007 Operating System Concepts with Java – 7 th Edition, Nov 15, 2006 Bakery Algorithm: “Take 1”  int ticket[n];  int next_ticket; CSEnter(int i) { ticket[i] = ++next_ticket; for(J = 0; J < N; J++) while(ticket[J] && ticket[J] < ticket[i]) continue; } CSExit(int i) { ticket[i] = 0; }  Oops… access to next_ticket is a problem!

26 6.26 Silberschatz, Galvin and Gagne ©2007 Operating System Concepts with Java – 7 th Edition, Nov 15, 2006 Bakery Algorithm: “Take 2”  int ticket[n]; CSEnter(int i) { ticket[i] = max(ticket[0], … ticket[N-1])+1; for(J = 0; J < N; J++) while(ticket[J] && ticket[j] < ticket[i]) continue; } CSExit(int i) { ticket[i] = 0; }  Clever idea: just add one to the max. Just add 1 to the max!  Oops… two could pick the same value!

27 6.27 Silberschatz, Galvin and Gagne ©2007 Operating System Concepts with Java – 7 th Edition, Nov 15, 2006 Bakery Algorithm: “Take 3” If i, j pick same ticket value, id’s break tie: (ticket[J] < ticket[i]) || (ticket[J]==ticket[i] && J

28 6.28 Silberschatz, Galvin and Gagne ©2007 Operating System Concepts with Java – 7 th Edition, Nov 15, 2006 Bakery Algorithm: “Take 4”  int ticket[N];  boolean picking[N] = false; CSEnter(int i) { ticket[i] = max(ticket[0], … ticket[N-1])+1; for(J = 0; J < N; J++) while(ticket[J] && (ticket[J],J) < (ticket[i],i)) continue; } CSExit(int i) { ticket[i] = 0; }  Oops… i could look at J when J is still storing its ticket, and yet J could have a lower id than me (i)!

29 6.29 Silberschatz, Galvin and Gagne ©2007 Operating System Concepts with Java – 7 th Edition, Nov 15, 2006 Bakery Algorithm: Almost final  int ticket[N];  boolean choosing[N] = false; CSEnter(int i) { choosing[i] = true; ticket[i] = max(ticket[0], … ticket[N-1])+1; choosing[i] = false; for(J = 0; J < N; J++) { while(choosing[J]) continue; while(ticket[J] && (ticket[J],J) < (ticket[i],i)) continue; } CSExit(int i) { ticket[i] = 0; }

30 6.30 Silberschatz, Galvin and Gagne ©2007 Operating System Concepts with Java – 7 th Edition, Nov 15, 2006 Bakery Algorithm: Issues?  What if we don’t know how many threads might be running? The algorithm depends on having an agreed upon value for N Somehow would need a way to adjust N when a thread is created or one goes away  Also, technically speaking, ticket can overflow! Solution: Change code so that if ticket is “too big”, set it back to zero and try again.

31 6.31 Silberschatz, Galvin and Gagne ©2007 Operating System Concepts with Java – 7 th Edition, Nov 15, 2006 Bakery Algorithm: Final  int ticket[N]; /* Important: Disable thread scheduling when changing N */  boolean choosing[N] = false; CSEnter(int i) { do { ticket[i] = 0; choosing[i] = true; ticket[i] = max(ticket[0], … ticket[N-1])+1; choosing[i] = false; } while(ticket[i] >= MAXIMUM); for(J = 0; J < N; J++) { while(choosing[J]) continue; while(ticket[J] && (ticket[J],J) < (ticket[i],i)) continue; } CSExit(int i) { ticket[i] = 0; }

32 6.32 Silberschatz, Galvin and Gagne ©2007 Operating System Concepts with Java – 7 th Edition, Nov 15, 2006 Approaches to Critical Sections  Everything we’ve seen so far is a software-only solution that relies on reads and writes being atomic Atomic = non-interruptible  Another approach: disable interrupts Disable interrupts briefly when calling CSEnter() and CSExit() Currently running code would execute without preemption Available only in the kernel (why?) Generally doesn’t work on multiprocessor systems Operating systems using this not broadly scalable  Modern machines provide hardware “help”: atomic instructions Either test memory word and set value (test and set) Or swap contents of two memory words (compare and swap)  Idea is to provide a mechanism for critical sections: a lock

33 6.33 Silberschatz, Galvin and Gagne ©2007 Operating System Concepts with Java – 7 th Edition, Nov 15, 2006 Critical Section Using Locks

34 6.34 Silberschatz, Galvin and Gagne ©2007 Operating System Concepts with Java – 7 th Edition, Nov 15, 2006 TestAndSet Instruction  Definition: boolean TestAndSet (boolean *target) { boolean rv = *target; *target = TRUE; return rv: }

35 6.35 Silberschatz, Galvin and Gagne ©2007 Operating System Concepts with Java – 7 th Edition, Nov 15, 2006 Solution using TestAndSet  Shared boolean variable lock., initialized to false.  Solution: while (true) { while ( TestAndSet (&lock )) ; /* do nothing // critical section lock = FALSE; // remainder section }

36 6.36 Silberschatz, Galvin and Gagne ©2007 Operating System Concepts with Java – 7 th Edition, Nov 15, 2006 Critical Sections using TestAndSet cs_enter: TSL REGISTER, LOCK // copy lock to reg and set to 1 CMP REGISTER, #0// was lock 0? JNE cs_enter// if so, loop RET// otherwise return, in critical sec cs_exit: STORE LOCK #0// set lock to 0 RET

37 6.37 Silberschatz, Galvin and Gagne ©2007 Operating System Concepts with Java – 7 th Edition, Nov 15, 2006 Swap Instruction  Definition: void Swap (boolean *a, boolean *b) { boolean temp = *a; *a = *b; *b = temp: }

38 6.38 Silberschatz, Galvin and Gagne ©2007 Operating System Concepts with Java – 7 th Edition, Nov 15, 2006  Shared Boolean variable lock initialized to FALSE; Each process has a local Boolean variable key.  Solution: while (true) { key = TRUE; while ( key == TRUE) Swap (&lock, &key ); // critical section lock = FALSE; // remainder section } Solution using Swap

39 6.39 Silberschatz, Galvin and Gagne ©2007 Operating System Concepts with Java – 7 th Edition, Nov 15, 2006 Critical Sections using Swap cs_enter: MOVE REGISTER, #1// put 1 in register XCHG REGISTER, LOCK// swap reg and lock contents CMP REGISTER, #0// was lock zero? JNE cs_enter// if not, loop RET// otherwise return, in cs cs_exit: MOVE LOCK, #0// store a zero in lock RET// return to caller

40 6.40 Silberschatz, Galvin and Gagne ©2007 Operating System Concepts with Java – 7 th Edition, Nov 15, 2006 Providing Critical Sections to Users  Everything we’ve seen so far involves busy waiting Also known as spin locks Acceptable for short waits (e.g., interrupts) Need a general-purpose mechanism that allows sleeping  Would like to provide higher-level abstractions to users CSEnter and CSExit are possibilities Operating systems have offer other primitives  E.g., semaphores, condition variables, mutexes Built out of low-level critical section operations More in next class

41 Silberschatz, Galvin and Gagne ©2007 Operating System Concepts with Java – 7 th Edition, Nov 15, 2006 End of Chapter 6 (a)


Download ppt "Silberschatz, Galvin and Gagne ©2007 Operating System Concepts with Java – 7 th Edition, Nov 15, 2006 Chapter 6 (a): Synchronization."

Similar presentations


Ads by Google