370 likes | 508 Views
Concurrency: Classic Problems and High-level abstractions. Fred Kuhns (fredk@arl.wustl.edu, http://www.arl.wustl.edu/~fredk) Department of Computer Science and Engineering Washington University in St. Louis. Classical Problems of Synchronization. Bounded-Buffer Problem
E N D
Concurrency: Classic Problems and High-level abstractions Fred Kuhns (fredk@arl.wustl.edu, http://www.arl.wustl.edu/~fredk) Department of Computer Science and Engineering Washington University in St. Louis
Classical Problems of Synchronization • Bounded-Buffer Problem • Readers and Writers Problem • Dining-Philosophers Problem Cs422 – Operating Systems Organization
Bounded-Buffer Problem • Shared datasemaphore full, empty, mutex;Initially:full = 0, empty = n, mutex = 1 Cs422 – Operating Systems Organization
Bounded-Buffer: Producer do { … produce an item in nextp … wait(empty); // Decrement free cnt wait(mutex); // Lock buffers … add nextp to buffer … signal(mutex); // release buffer lock signal(full); // Increment item count } while (1); Cs422 – Operating Systems Organization
Bounded-Buffer: Consumer do { wait(full) // decrement item count wait(mutex); // lock buffers … remove item from buffer nextc … signal(mutex); // release lock signal(empty); // increment free count … consume item in nextc … } while (1); Cs422 – Operating Systems Organization
Readers-Writers • Reader tasks and writer tasks share a resource, say a database • Many readers may access a database without fear of data corruption (interference) • However, only one write may access the database at a time (all other readers and writers must be “locked” out of database. • Solutions: • simple solution gives priority to readers. Readers enter CS regardless of whether a write is waiting • writers may starve • second solution requires once a write is ready, it gets to perform its write as soon as possible • readers may starve Cs422 – Operating Systems Organization
Readers-Writers Problem • The simple solution is presented: • Shared datasemaphore mutex, wrt;Initiallymutex = 1, wrt = 1, readcount = 0 Cs422 – Operating Systems Organization
Readers-Writers Problem: Writer wait(wrt); … writing is performed … signal(wrt); Cs422 – Operating Systems Organization
Readers-Writers Problem: Reader wait(mutex); readcount++; if (readcount == 1) // First reader wait(wrt); // then get lock signal(mutex); … reading is performed … wait(mutex); readcount--; if (readcount == 0) // Last reader signal(wrt); // then release lock signal(mutex): Cs422 – Operating Systems Organization
Dining-Philosophers Problem • Shared data semaphore chopstick[5]; Initially all values are 1 Cs422 – Operating Systems Organization
Dining-Philosophers Problem • Philosopher i: do { wait(chopstick[i]) wait(chopstick[(i+1) % 5]) … eat … signal(chopstick[i]); signal(chopstick[(i+1) % 5]); … think … } while (1); Cs422 – Operating Systems Organization
Potential Problems • Incorrect use of semaphores can lead to problems • Critical sections using semaphores: must keep to a strict protocol • wait(S); {critical section}; signal(S) • Problems: • No mutual exclusion: • Reverse: signal(S); {critical section}; wait(S); • Omit wait(S) • Deadlock: • wait(S); {critical section}; wait(S); • Omit signal(S) Cs422 – Operating Systems Organization
Potential Solutions • How do we protect ourselves from these kinds of errors? • Develop language constructs that can be validated automatically by the compiler or run-time environment • Critical Regions • Monitors Cs422 – Operating Systems Organization
Critical Regions • High-level synchronization construct • A shared variable v of type T, is declared as: v: shared T • Variable v accessed only inside statement region v when B do Swhere B is a Boolean expression. • While statement S is being executed, no other process can access variable v. Cs422 – Operating Systems Organization
Critical Regions • Regions referring to the same shared variable exclude each other in time. • When a process tries to execute the region statement, the Boolean expression B is evaluated. If B is true, statement S is executed. If B is false, the process is delayed until B becomes true and no other process is in the region associated with v. Cs422 – Operating Systems Organization
Critical Regions: Bounded Buffer struct buffer { int pool[n]; int count, in, out; } Producer: region buffer when (count < n) { pool[in] = nextp; in = (in+1) % n; count++; } Consumer: region buffer when (count > 0) { nextc = pool[out]; out = (out+1) % n; count--; } Cs422 – Operating Systems Organization
Monitors • High-level synchronization construct that allows the safe sharing of an abstract data type among concurrent processes. monitor monitor-name { shared variable declarations procedure body P1 (…) { . . . } procedure body P2 (…) { . . . } procedure body Pn (…) { . . . } { initialization code } } Cs422 – Operating Systems Organization
Schematic View of a Monitor Cs422 – Operating Systems Organization
Monitors: Condition Variables • To allow a process to wait within the monitor, a condition variable must be declared, as conditionx, y; • Condition variable can only be used with the operations wait and signal. • The operation x.wait();means that the process invoking this operation is suspended until another process invokes x.signal(); • The x.signal operation resumes exactly one suspended process. If no process is suspended, then the signal operation has no effect. Cs422 – Operating Systems Organization
Monitors: Condition Variables • If a task A within a monitor signals a suspended task B, there is an issue of who then gets to continue executing within the monitor. • Task A waits for B to leave the monitor or waits on another condition • Task B waits for A to leave the monitor or waits for another condition • A case can be made for either approach Cs422 – Operating Systems Organization
Monitor With Condition Variables Cs422 – Operating Systems Organization
Dining Philosophers Example monitor dp { enum {thinking, hungry, eating} state[5]; condition self[5]; void pickup(int i) ; void putdown(int i); void test(int i); void init() { for (int i = 0; i < 5; i++) state[i] = thinking; } } Cs422 – Operating Systems Organization
Dining Philosophers 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 test((i+4) % 5); test((i+1) % 5); } void test(int i) { if ( (state[(i + 4) % 5] != eating) && (state[i] == hungry) && (state[(i + 1) % 5] != eating)) { state[i] = eating; self[i].signal(); } } Solution: dp.pickup(i); ... eat ... dp.putdown(i); Cs422 – Operating Systems Organization
Monitor Implementation • Since only one task may be active in a monitor there must be a mutex protecting each method. • We also need to account for sending signals within a monitor – that is, guard against having more than one active task within the monitor. • Our implementation uses semaphores for both mutual exclusion (initialized to 1 for a mutex) and counting the number of tasks waiting to be resumed within the monitor (initialized to 0 – counting semaphore) Cs422 – Operating Systems Organization
Example Implementation semaphore mutex; // protect monitor semaphore next; // waiting to be resumed int next_count = 0; • Each external method Mwill be replaced by wait(mutex); // ensures mutual exclusion … body of M; … if (next_count > 0) // tasks waiting to be resumed signal(next) // resume them else signal(mutex); // else unlock monitor Mutual exclusion within a monitor is ensured. Cs422 – Operating Systems Organization
Example Implementation: CV • Implement so that the signaling task waits to complete • For each condition variable cv, we have: semaphore cv_sem; // (initially = 0) int cv_count = 0; cv.signal: if (cv_count > 0) { next-count++; signal(cv_sem); wait(next); next-count--; } cv.wait: cv_count++; if (next_count > 0) signal(next); else signal(mutex); wait(cv_sem); cv_count--; Cs422 – Operating Systems Organization
More on Monitor Implementations • How can we control the task resumption order? • Conditional-wait construct: x.wait(c); c – integer expression evaluated when wait executed. • value of c (a priority number) stored with the name of the process that is suspended. • when x.signal is executed, process with smallest associated priority number is resumed next. • Verifying correctness: Check two conditions: • User processes must always make their calls on the monitor in a correct sequence. • Must ensure that an uncooperative process does not ignore the mutual-exclusion gateway provided by the monitor, and try to access the shared resource directly, without using the access protocols. Cs422 – Operating Systems Organization
OS Synchronization • spin locks (simple mutex), • blocking locks (mutex) • adaptive mutex • condition variables Cs422 – Operating Systems Organization
Spin Locks or Simple Mutexes • The idea is to provide a basic, HW supported primitive with lowoverhead. • Lock held for shortperiods of time • If locked, then busy-wait on the resource • Must not give up processor! In other words, can not block. Cs422 – Operating Systems Organization
Spin-Lock implementation void spin_lock (spinlock_t *s) { while (test_and_set (s) != 0) while (*s != 0) ; } void spin_unlock (spinlock_t *s) { s = 0; } Cs422 – Operating Systems Organization
Blocking Locks/Mutex • Allows threads to block • Interface: • lock(), unlock () and trylock () • Consider traditional kernel locked flag • Mutex allows for exclusive access to flag, solving the race condition • flag can be protected by a spin lock. Cs422 – Operating Systems Organization
Condition variables • Associated with a predicate which is protected by a mutex (usually a spin lock). • Useful for event notification • Can wakeup one or all sleeping threads! Cs422 – Operating Systems Organization
Condition Variables • Up to 3 or more mutex are typically required: • one for the predicate • one for the sleep queue (or CV list) • one or more for the scheduler queue (swtch ()) • deadlock avoided by requiring a strict order Cs422 – Operating Systems Organization
predicate Condition variable mutex List of blocked threads mutex (for list) kthread_3 kthread_2 kthread_1 Condition Variables update predicate wake up one thread Thread sets event Cs422 – Operating Systems Organization
CV Implementation Void do_signal (cv *c) { lock (&cv->listlock); -- remove 1 thread -- unlock (&cv->listlock); if thread, make runnable; return; } voiddo_broadcast (cv *c) { lock (&cv->listlock); while (list is nonempty) { remove a thread make it runnable} unlock (&cv->listlock); return;} wait() called with mutex s already locked. Void wait (cv *c, mutex_t *s) { lock (&cv->listlock); -- add thread to queue -- unlock (&cv->listlock); unlock (s); swtch (); /* return => after wakup */ lock (s); return; } Cs422 – Operating Systems Organization
Solaris 2 Synchronization • Implements a variety of locks to support multitasking, multithreading (including real-time threads), and multiprocessing. • Uses adaptive mutexes for efficiency when protecting data from short code segments. • Uses condition variablesand readers-writers locks when longer sections of code need access to data. • Uses turnstiles to order the list of threads waiting to acquire either an adaptive mutex or reader-writer lock. Cs422 – Operating Systems Organization
Windows 2000 Synchronization • Uses interrupt masks to protect access to global resources on uniprocessor systems. • Uses spinlocks on multiprocessor systems. • Also provides dispatcher objects which are used by user space threads and act as either mutexes, semaphores or events. • An event acts much like a condition variable. • signaled or unsignaled state Cs422 – Operating Systems Organization