Classical Problems of Synchronization These slides are adapted
Classical Problems of Synchronization These slides are adapted from Operating Systems Concepts textbook, 8 th edition, Silberscatz, Galvin, Gagne.
Bounded-Buffer Problem • N buffers, each can hold one item • Semaphore mutex initialized to the value 1 • Provides mutual exclusion for accesses to the buffer pool • Semaphore full initialized to the value 0 • Number of full buffers • Semaphore empty initialized to the value N. • Number of empty buffers
Bounded Buffer Problem (Cont. ) • The structure of the producer process while (true) { // produce an item wait (empty); wait (mutex); // add the item to the buffer signal (mutex); signal (full); }
Bounded Buffer Problem (Cont. ) • The structure of the consumer process while (true) { wait (full); wait (mutex); // remove an item from buffer signal (mutex); signal (empty); // consume the removed item }
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 (exclusive access) • Variations: • First readers-writers problem: Requires that no reader will be kept waiting unless a writer has already obtained permission to use the shared object. No reader should wait for other readers to finish simply because a writer is waiting. • Second readers-writers problem: Requires that once a writer is ready, that writer performs its write as soon as possible. If a writer is waiting to access the object, no new readers may start reading. • In the first case writers may starve; in the second case, readers may starve. We present a solution to the first readers-writers problem.
Readers-Writers Problem • Shared Data • Data set • Semaphore mutex initialized to 1. • Ensures mutual exclusion when readcount is updated. • Semaphore wrt initialized to 1. • A mutual exclusion semaphore for the writers. Also used by the first or last reader that enters or exits the critical section. • Integer readcount initialized to 0. • Keeps track of how many processes are currently reading the object. • If a writer is in the critical section and n readers waiting, then one reader is queued on wrt, and n-1 readers are queued on mutex. • When a writer executes signal(wrt), we may resume the execution of either the waiting readers or a single waiting writer. The selection is made by the scheduler.
Readers-Writers Problem (Cont. ) • The structure of a writer process while (true) { wait (wrt) ; // writing is performed signal (wrt) ; }
Readers-Writers Problem (Cont. ) • The structure of a reader process while (true) { wait (mutex) ; readcount ++ ; if (readcount == 1) wait (wrt) ; signal (mutex) // reading is performed } wait (mutex) ; readcount - - ; if (readcount == 0) signal (wrt) ; signal (mutex) ;
Dining-Philosophers Problem Philosophers think or eat. A philosopher may pick up only one chopstick at a time She cannot pick up a chopstick that is already in the hand of a neighbor. When a hungry philosopher has both her chopstick at the same time, she eats without releasing her chopsticks. • When she is finished eating, she puts down both of her chopsticks and starts thinking again. • •
Dining-Philosophers Problem • Shared data • Bowl of rice (data set) • Semaphore chopstick [5] initialized to 1 • This solution guarantees that no two neighbors are eating simultaneously, but it can create a deadlock. Suppose that all five philosophers become hungry simultaneously and each grabs her left chopstick. When each philosopher tries to grab her right chopstick, she will be delayed forever. • Remedies to deadlock problem • Allow at most four philosophers to be sitting simultaneously at the table. • Allow a philosopher to pick up her chopsticks only if both chopsticks are available (she must pick them up in a critical section) • Use an asymmetric solution; that is an odd philosopher picks up first her left chopstick and then her right chopstick, whereas an even philosopher picks up her right chopstick and then her left chopstick. • A deadlock-free solution does not necessarily eliminate the possibility of starvation.
Dining-Philosophers Problem (Cont. ) • The structure of Philosopher i: While (true) { wait ( chopstick[i] ); wait ( chop. Stick[ (i + 1) % 5] ); // eat signal ( chopstick[i] ); signal (chopstick[ (i + 1) % 5] ); // think }
Problems with Semaphores • Incorrect use of semaphore operations: • signal (mutex). . . Critical section. . . wait (mutex) • Several processes may be executing in their critical sections • wait (mutex) … Critical section. . . wait (mutex) • A deadlock will occur • Omitting of wait (mutex) or signal (mutex) (or both) • Either mutual exclusion is violated or a deadlock will occur
Monitors • A high-level abstraction that provides a convenient and effective mechanism for process synchronization • Only one process may be active within the monitor at a time (operations are provided mutual exclusion) • Also contains the declaration of variables whose values define the state. • A procedure defined within a monitor can access only those variables declared locally within the monitor and its formal parameters monitor-name { // shared variable declarations procedure P 1 (…) { …. } … procedure Pn (…) {……} } Initialization code ( …. ) { … }
Condition Variables • 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) that invoked x. wait ()
Monitors • Suppose that, when the x. signal() operation is invoked by a process P, there is a suspended process Q associated with condition x. • If the suspended process Q is allowed to resume its execution, the signaling process P must wait. Otherwise, both P and Q would be active simultaneously within the monitor. • Two solutions: • 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.
Monitor with Condition Variables
Deadlock free 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); }
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;
Solution to Dining Philosophers (cont) • Each philosopher I invokes the operations pickup() and putdown() in the following sequence: dp. pickup (i) EAT dp. putdown (i) • This solution imposes the restriction that a philosopher may pick up her chopsticks only if both of them are available. • No deadlocks will occur. • But, it is possible for a philosopher to starve to death.
Monitor Implementation Using Semaphores • Variables • semaphore mutex; // (initially = 1) • semaphore next; // (initially = 0) • On which the signaling processes may suspend themselves. • int next-count = 0; • Counts the number of processes suspended on next • Each procedure F will be replaced by wait(mutex); … body of F; … if (next-count > 0) signal(next) else signal(mutex); • Mutual exclusion within a monitor is ensured.
Monitor Implementation • For each condition variable x, we have: semaphore x-sem; // (initially = 0) int x-count = 0; • The operation x. wait can be implemented as: x-count++; if (next-count > 0) signal(next); else signal(mutex); wait(x-sem); x-count--;
Monitor Implementation • The operation x. signal can be implemented as: if (x-count > 0) { next-count++; signal(x-sem); wait(next); next-count--; }
- Slides: 22