Synchronization II: CPE Operating Systems
Classical Problems of Synchronization Bounded-Buffer Problem (6.6.1) Dining-Philosophers Problem (6.6.3) (Readers-Writers Problem 6.6.2)
Bounded-Buffer Problem while (true) { // produce an item wait (empty); wait (mutex); // add the item to the buffer signal (mutex); signal (full); } while (true) { wait (full); wait (mutex); // remove an item from buffer signal (mutex); signal (empty); // consume the removed item } Producer Consumer 10N MutexFullEmpty Semaphores
Human Error is Hard to Debug
Monitors Higher level API than Semaphores Can help prevent human error Figure 6.19
Bounded Buffer Problem monitor BoundedBuffer { function Produce (value) { if BufferLen < N // Add a value to Buffer } Function consume() { If BufferLen > 0 // remove a value from Buffer } // usage example BoundedBuffer.Produce(x) BoundedBuffer.Consume()
Bounded Buffer Problem monitor BoundedBuffer { Condition content Condition emptySpace function Produce (value) { if BufferLen < N // Add a value to Buffer content.signal() else emptySpace.wait() } Function consume() { If BufferLen > 0 // remove a value from Buffer emptySpace.signal() else content.wait() }
Counting Semaphores vs Conditions Semaphore i = 0 Signal (i) // i will = 1 Condition i i.signal() // nothing happens // if not waiting // process Counting Semaphores Condition (Less bugs)
Dining-Philosophers Problem Figure 6.16
A solution using Semaphores Every philosopher runs this code While (true) { wait ( chopstick[i] ); wait ( chopStick[ (i + 1) % 5] ); // eat signal ( chopstick[i] ); signal (chopstick[ (i + 1) % 5] ); // think }
Deadlock?
Using Monitors 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); }
Using Monitors (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; }