310 likes | 714 Views
Semaphores and Monitors. CIS450 Winter 2003 Professor Jinhua Guo. Mutual Exclusion with Swap. Initially, s == false; entry () { bool spin = true; Swap(spin, s); while (spin) Swap(spin, s); } exit() { s = false; }. Semaphores (Dijkstra).
E N D
Semaphores and Monitors CIS450 Winter 2003 Professor Jinhua Guo
Mutual Exclusion with Swap Initially, s == false; entry () { bool spin = true; Swap(spin, s); while (spin) Swap(spin, s); } exit() { s = false; }
Semaphores (Dijkstra) • Synchronization tool that does not require busy waiting. • Semaphore is an object contains a (private) integer value and 2 operations. • P operation, also called Down or Wait • Take a resource • V operation, also called Up or Signal • Release a resource • Semaphores are “resource counters”.
Semaphore Implementation • Define a semaphore as a record typedef struct { int value; struct process *L; } semaphore; • Assume two simple operations: • block(), suspends the process that invokes it. • wakeup(P), changes the thread from the waiting state to the ready state.
Implementation • Semaphore operations now defined as P(S): S.value--; if (S.value < 0) { add this process to S.L; block(); } V(S): S.value++; if (S.value <= 0) { remove a process P from S.L; wakeup(P); } • The P and V operations are atomic.
Critical Sections with Semaphores semaphore mutex = 1; entry() P(mutex); exit() V(mutex); • For mutual exclusion, initialize semaphore to 1.
Semaphore as a General Synchronization Tool • Execute B in Pj only after A executed in Pi • Use semaphore flag initialized to 0 • Code: Pi Pj AP(flag) V(flag) B
Bounded Buffer Problem • There is one Buffer object used to pass objects from producers to consumers. The problem is to allow concurrent access to the Buffer by producers and consumers, while ensuring that • The shared Buffer data structure is not screwed up by race conditions in accessing it. • Consumers don't try to remove objects from Buffer when it is empty. • Producers don't try to add objects to the Buffer when it is full.
Producer() while (1) { produce message m; P(empty); buf[rear] = m; rear = rear “+”1; V(full); } Consumer () while (1) { P(full); m = buf[front]; front = front “+” 1; V(empty); consume m; } Bounded Buffer (1 producer, 1 consumer) char buf[n], int front = 0, rear = 0; semaphore empty = n, full = 0;
Bounded Buffer (multiple producers and consumers) char buf[n], int front = 0, rear = 0; semaphore empty = n, full = 0, mutex = 1; Producer() while (1) { produce message m; P(empty); P(mutex); buf[rear] = m; rear = rear “+”1; V(mutex); V(full) } Consumer () while (1) { P(full); P(mutex); m = buf[front]; front = front “+” 1; V(mutex); V(empty); consume m; }
Deadlock and Starvation • Deadlock – two or more processes are waiting indefinitely for an event that can be caused by only one of the waiting processes. Let S and Q be two semaphores initialized to 1 P0P1 P(S); P(Q); P(Q); P(S); V(S); V(Q); V(Q); V(S); • Starvation – indefinite blocking. A process may never be removed from the semaphore queue in which it is suspended.
Readers-Writers Problem • Given a database Can have multiple “readers” at a time don’t ever modify database Only one “writer” will modify database • The problem has many variation
Readers-Writers Problem Semaphore Solution • Shared datasemaphore mutex = 1, wrt = 1;int readcount = 0; • Writer ProcesswriteEnter () { P(wrt); } writeExit () { V(wrt); }
Reader Process readEnter () { P(mutex); readcount++; if (readcount == 1) P(wrt); V(mutex); } readExit() { P(mutex); readcount--; if (readcount == 0) V(wrt); V(mutex); }
Dining-Philosophers Problem • Shared data semaphore chopstick[5]; Initially all values are 1
Dining-Philosophers Problem Philosopher i: do { P(chopstick[i]) P(chopstick[(i+1) % 5]) … eat … V(chopstick[i]); V(chopstick[(i+1) % 5]); … think … } while (1);
Dining-Philosophers Problem(Deadlock Free) • Philosopher i: do { if (i ! = 0) { P(chopstick[i]); P(chopstick[i+1]); … eat … V(chopstick[i]); V(chopstick[i+1]); } else { P(chopstick[1]); P(chopstick[0]); … eat … V(chopstick[1]); V(chopstick[0]); } … think … } while (1);
Problems with Semaphores • Used for 2 independent purposes • Mutual exclusion • Condition Synchronization • Hard to get right • Small mistake easily leads to deadlock May want to separate mutual exclusion, condition synchronization
Monitors (Hoare) • Abstract Data Type • Consists of vars and procedures, like C++ class. • 3 key differences from a regular class: • Only one thread in monitor at a time (mutual exclusion is automatic); • Special type of variable allowed, called “condition variable” • 3 special ops allowed only on condition variables: wait, signal, broadcast • No public data allowed (must call methods to effect any change)
Monitors monitor monitor-name { shared variable declarations procedure bodyP1(…) { . . . } procedurebodyP2 (…) { . . . } procedure bodyPn(…) { . . . } { initialization code } }
Monitors • To allow a process to wait within the monitor, a condition variable must be declared, as condition x, y, cond; • Given a condition variable “cond” • cond.wait(): • thread is put on queue for “cond”, goes to sleep • cond.signal(): • if queue for “cond” not empty, wakeup one thread • cond.broadcast • wakeup all threads waiting on queue for “cond”
Semantics of Signal • Signal and Wait (Hoare) • signaller immediately gives up control • thread that was waiting executes • Signal and Continue (Java, Pthread, Mesa) • signaller continues executing • thread that was waiting put on ready queue • when thread actually gets to run • State may have changed! Use “while”, not “if”
Monitor Solution to Critical Section • Just make the critical section a monitor routine!
Readers/Writers Solution Using Monitors • Similar idea to semaphore solution • Simpler, because don’t worry about mutex • When can’t get into database, wait on appropriate condition variable • When done with database, signal others Note: can’t just put code for “reading database” and code for “writing database” in the monitor (could’t have >1 reader)
Difference between Monitors and Semaphores • Monitors enforce mutual exclusion • P() vs Wait • P blocks if value is 0, Wait always blocks • V() vs Signal • V either wakes up a thread or increments value • Signal only has effect if a thread waiting • Semaphores have “memory”
Implementing Monitors using Semaphores • Shared vars: • semaphore mutex = 1(one per monitor) • semaphore c = 0; (one per condition var) • int nc = 0; (one per condition var) • Monitor entry: P(mutex); • Monitor exit: V(mutex);
Implementing Monitors using Semaphores • cond->Wait(mutex): nc++; V(mutex); P(c); P(mutex); • cond->Signal(): if (nc > 0) { nc--; V(c); }
Java-style monitors • Integrated into the class mechanism • Annotation “synchronized” can be applied to a member function • This function executes with implicit mutual exclusion • Wait, Signal, and Broadcast are called mon wait, notify, and notifyAll, respectively