Quick viewing(Text Mode)

Synchronization: Semaphores, Monitors, and Condition Variables

Synchronization: Semaphores, Monitors, and Condition Variables

Today’s Topics

u Mutex Isn’t Enough COS 318: Operating Systems u Semaphores u Condition Variables Synchronization: Semaphores, u Monitors Monitors and Condition Variables u Barriers

Jaswinder Pal Singh and a Fabulous Course Staff Computer Science Department Princeton University

(http://www.cs.princeton.edu/courses/cos318/)

2

Revisit Mutex Producer-Consumer (Bounded Buffer) Problem

u Mutex can solve the problem Acquire( ); Producer: Consumer: while (1) { Critical section while (1) { produce an item remove an item from buffer Release( lock ); Insert item in buffer count--; u Use Mutex primitives to access shared data structures count++; consume an item E.g. shared “count” variable } } Acquire( lock ); count = 4 count++; Release( lock ); N = 12

u Are mutex primitives adequate to solve all problems? u Can we solve this problem with Mutex primitives?

3 4

1 Use Mutex, Block and Unblock Use Mutex, Block and Unblock

Producer: Consumer: Producer: Consumer: while (1) { while (1) { while (1) { while (1) { produce an item if (!count) produce an item if (!count) if (count == N) Block(); if (count == N) { switch} Block(); remove an item from buffer Block(); Block(); Insert item in buffer Acquire(lock); Insert item in buffer remove an item from buffer Acquire(lock); count--; Acquire(lock); Acquire(lock); count++; Release(lock); count++; count--; Release(lock); if (count == N-1) Release(lock); Release(lock); if (count == 1) count = 4 Unblock(Producer); if (count == 1) countcountcount = == 12 01 if (count == N-1) Unblock(Consumer); consume an item Unblock(Consumer); Unblock(Producer); } N = 12 } } N = 12 consume an item }

u Does this work? u ! u Ultimately, both block and never wake up u Lost the unblock; any way to “remember” them? 5 6

Limitations of Locks Semaphores (Dijkstra, 1965)

u A is a synchronization variable that contains an u Provide : only one / can be in the integer value critical section at a time l Cannot access the integer value directly (only via semaphore operations) u Do not provide ordering or sequencing (aka event synchronization) l Initialized to some integer value l Who gets to be in critical section first? l Supports two atomic operations other than initialization l How does thread A wait for thread B (or , D, E) to do X before A does Y? • down() (or wait() or P()) u Need additional synchronization mechanisms • up (or signal() or V()) l Semaphores u If positive value, think of value as keeping track of how many ‘resources’ or “un-activated unblocks” are available l Condition Variables u If negative, tracks how many threads are waiting for a resource l Monitors or unblock l (Higher level constructs composed from these)

7 8

2 Semaphores (Dijkstra, 1965) Bounded Buffer with Semaphores

“ ” u P (or Down or Wait or Proberen (to try)) definition Producer: Consumer: l Atomic operation while (1) { while (1) { l Block version: Decrement value, and if result less than zero then block produce an item P(fullCount); l Spin version: Wait for semaphore to become positive and then decrement P(emptyCount); P(s){ P(s){ P(mutex); if (--s < 0) while (s <= 0) P(mutex); take an item from buffer block(s); ; put item in buffer V(mutex); s--; V(mutex); } } V(emptyCount); V(fullCount); consume item u V (or Up or Signal or “Verhogen” (increment)) definition } } l Atomic operation l Block version: increment, and if non-positive (which means at least one thread is blocked waiting on the sempahore) then unblock a thread u Initialization: emptyCount = N; fullCount = 0 l Spin version: Increment semaphore u Are P(mutex)and V(mutex) necessary? V(s){ V(s){ if (++s <=0) s++; unblock(s); } } 9

Uses of Semaphores in this Example Example: Handler

u Event sequencing l Don’t consume if buffer empty, wait for something to be Init(s,0); added l Don’t add if buffer full, wait for something to be removed Device thread Interrupted Thread u Mutual exclusion while (1) { P(s); … l Avoid race conditions on shared variables Acquire(m); ...... Interrupt deal with interrupt V(s); … ...... Release(m); }

11 12

3 Bounded Buffer with Semaphores (again) Does Order Matter?

producer() { consumer() { producer() { consumer() { while (1) { while (1) { while (1) { while (1) { produce an item P(fullCount); produce an item P(fullCount); P(emptyCount); P(mutex); P(mutex); P(emptyCount); P(mutex); P(mutex); take an item from buffer take an item from buffer put the item in buffer V(mutex); put the item in buffer V(mutex); V(mutex); V(mutex); V(emptyCount); V(emptyCount); V(fullCount); consume the item V(fullCount); consume the item } } } } } } } }

Another Example: Are Locks Enough? Condition Variables

u Make tryRemove wait until something is on the queue? u A lock provides mutual exclusion to the shared data l Can’t just sleep while holding the lock u Rules for using a lock: l Key idea: make it possible to go to sleep inside critical section, l Always acquire before accessing shared data structure by atomically releasing lock at same time we go to sleep. l Always release after finishing with shared data l Lock is initially free. u Condition variable: enables a queue of threads waiting for something inside a critical section. u Simple example: a synchronized queue l Wait() --- Release lock, go to sleep, re-acquire when woken • release lock and going to sleep is atomic bool tryRemove() bool tryInsert() { … { lock.Acquire(); l Signal() --- Wake up a waiter, if any lock.Acquire(); // lock before use if something on queue // can we wait? l Broadcast() --- Wake up all waiters … put item on queue; // ok to access remove it; lock.Release(); // unlock after done lock->Release(); return success; return success; } }

4 Synchronized Queue Condition variable design pattern

u Rule: must hold lock when doing condition variable methodThatWaits() { methodThatSignals() { operations lock.acquire(); lock.acquire();

RemoveFromQueue() // Read/write shared state // Read/write shared state AddToQueue() { { lock.acquire(); lock.acquire(); while (!testSharedState()) { // If testSharedState is now true while nothing on queue cv.wait(&lock); cv.signal(&lock); put item on queue; condition.wait(&lock); } condition.signal(); // release lock; got to // sleep; reacquire lock // Read/write shared state // Read/write shared state lock.release(); // when woken } lock.release(); remove item from queue; lock.release(); } lock.release(); } return item; }

Condition variables Structured synchronization

u ALWAYS hold lock when calling wait, signal, broadcast u Identify objects or data structures that can be accessed l Condition variable is synchronization FOR shared state by multiple threads concurrently l Remember: ALWAYS hold lock when accessing shared state u Add locks to object/module l Obtain lock on start to every method/procedure u Unlike semaphore, condition variable is memory-less l Release lock when finished l If signal when no one is waiting, no op u If need to wait l If signal after a wait is posted, a waiter wakes up l while(needToWait()) { condition.Wait(lock); } u If do something that should wake someone up u Wait atomically releases lock l Signal or Broadcast u Always leave shared state variables in a consistent state l When lock is released, or when waiting

5 Monitors Monitors Embedded in Languages

u High-level data abstraction that unifies handling of: u Monitor definition: l Shared data, operations on it, synchronization and l a lock and zero or more condition variables for managing • All operations on data structure have single (implicit) lock concurrent access to shared data • An operation can relinquish control and wait on condition // only one process at time can update instance of Q u Monitors make things easier: class Q { int head, tail; // shared data l “locks” for mutual exclusion void enqueue(v) { locked access to Q instance } l “condition variables” for scheduling constraints int dequeue() { locked access to Q instance } }

l Java from Sun; /Cedar from Xerox PARC u Monitors are easy and safe l Compiler can check, lock is implicit (cannot be forgotten)

Monitor: Hide Mutual Exclusion Condition Variables in A Monitor u Brinch-Hansen (73), Hoare (74) u Wait(condition) Queues associated u Procedures are mutually exclusive l Block on “condition” with x, y u Signal(condition) conditions x Shared l Wakeup a blocked process y data on “condition” Queue of waiting processes Shared trying to enter the monitor data ...

procedures ... Entry queue procedures

6 Producer-Consumer with Monitors Hoare’s Signal Implementation (MOS p137)

monitor ProdCons procedure Producer monitor ProdCons u Run the signaled thread condition full, empty; condition full, empty; begin immediately and suspend while true do procedure Enter; begin procedure Enter; the current one (Hoare) begin produce an item begin if (buffer is full) ProdCons.Enter(); if (buffer is full) wait(full); wait(full); end; u What if the current thread end; put item into buffer; put item into buffer; if (only one item) has more things to do? if (only one item) signal(empty); procedure Consumer signal(empty); end; end; begin if (only one item) while true do signal(empty); procedure Remove; begin procedure Remove; something else begin ProdCons.Remove(); begin end; consume an item; if (buffer is empty) if (buffer is empty) wait(empty); end; wait(empty); end; remove an item; remove an item; if (buffer was full) if (buffer was full) signal(full); signal(full); end; end; 31

Hansen’s Signal Implementation (MOS p 137) Mesa Signal Implementation

u Signal must be the last monitor ProdCons u Continues its execution statement of a monitor condition full, empty; if (only one item) signal(empty); procedure procedure Enter; something else begin u end; Exit the monitor if (buffer is full) wait(full); put item into buffer; l B. W. Lampson and D. D. Redell, “Experience with Processes and u Any issue with this if (only one item) Monitors in Mesa,” Communiction of the ACM, 23(2):105-117. 1980. approach? signal(empty); end; u This is easy to implement!

procedure Remove; begin u Issues? if (buffer is empty) wait(empty); remove an item; if (buffer was full) signal(full); end; 32 33

7 Evolution of Monitors Barrier Synchronization

u Brinch-Hansen (73) and Hoare Monitor (74) u Thread A and Thread B l Concept, but no implementation want to meet at a Thread A Thread B l Requires Signal to be the last statement (Hansen) l Requires relinquishing CPU to waiting signaled thread (Hoare) particular point u Mesa Language (77) u The one to get there first l Monitor in language, but signaler keeps mutex and CPU waits for the other one to l Waiter simply put on ready queue, with no special priority reach that point before u Modula-2+ (84) and Modula-3 (88) l Explicit LOCK primitive proceeding l Mesa-style monitor u Then both go forward u Pthreads (95) l Started standard effort around 1989 l Defined by ANSI/IEEE POSIX 1003.1 Runtime library u Java threads l James Gosling in early 1990s without threads l Use most of the Pthreads primitives

42

Using Semaphores as A Barrier Barrier Primitive

u Use two semaphores? u Functions init(s1, 0); l Take a barrier variable init(s2, 0); l Broadcast to n-1 threads Thread 1 Thread n … . . . … l When barrier variable has Barrier(b); Barrier(b); Thread A Thread B reached n, go forward … … … … V(s1); V(s2); u Hardware support on P(s2); P(s1); some parallel machines … … l Multicast network l Counting logic u What about more than two threads? Barrier l User-level barrier variables variable

43 44

8 Equivalence The Big Picture u Semaphores l Good for signaling and fine for simple mutex l Not good for mutex in general, since easy to introduce a bug OS codes and concurrent applications with ordering against other semaphores • Locks are only for mutex, so clearer and less bug-prone High-Level Mutex Semaphores Monitors Barriers Atomic API u Monitors l Good for scheduling and mutex Low-Level Interrupt Other atomic Load/store Test&Set l May be costly for simple signaling Atomic Ops disable/enable instructions

Interrupts CPU Multiprocessors (I/O, timer) scheduling

45 46

Summary u Mutex alone are not enough u Semaphores u Monitors l Mesa-style monitor and its idiom u Barriers

47

9