CS162 Operating Systems and Systems Programming Lecture 8 Readers-Writers Language Support for SynchronizationReview: Implementation of Locks by Disabling InterruptsReview: How to Re-enable After Sleep()?Review: Locks using test&setReview: SemaphoresGoals for TodayReview: Full Solution to Bounded BufferDiscussion about SolutionMotivation for Monitors and Condition VariablesSimple Monitor Example (version 1)Condition VariablesComplete Monitor Example (with condition variable)Mesa vs. Hoare monitorsAdministriviaAdministrivia (con’t)Using of Compare&Swap for queuesReaders/Writers ProblemBasic Readers/Writers SolutionCode for a ReaderCode for a WriterSimulation of Readers/Writers solutionSimulation(2)Simulation(3)QuestionsCan we construct Monitors from Semaphores?Construction of Monitors from Semaphores (con’t)Monitor ConclusionC-Language Support for SynchronizationC++ Language Support for SynchronizationC++ Language Support for Synchronization (con’t)Java Language Support for SynchronizationJava Language Support for Synchronization (con’t)Java Language Support for Synchronization (con’t 2)SummaryCS162Operating Systems andSystems ProgrammingLecture 8Readers-WritersLanguage Support for SynchronizationSeptember 23, 2009Prof. John Kubiatowiczhttp://inst.eecs.berkeley.edu/~cs162Lec 8.29/23/09 Kubiatowicz CS162 ©UCB Fall 2009Review: Implementation of Locks by Disabling Interrupts•Key idea: maintain a lock variable and impose mutual exclusion only during operations on that variableint value = FREE;Acquire() {disable interrupts;if (value == BUSY) {put thread on wait queue;Go to sleep();// Enable interrupts?} else {value = BUSY;}enable interrupts;}Release() {disable interrupts;if (anyone on wait queue) {take thread off wait queuePlace on ready queue;} else {value = FREE;}enable interrupts;}Lec 8.39/23/09 Kubiatowicz CS162 ©UCB Fall 2009Review: How to Re-enable After Sleep()?•In Nachos, since ints are disabled when you call sleep:–Responsibility of the next thread to re-enable ints–When the sleeping thread wakes up, returns to acquire and re-enables interruptsThread AThread B..disable intssleepsleep returnenable ints...disable intsleepsleep returnenable ints..contextswitchcontextswitchLec 8.49/23/09 Kubiatowicz CS162 ©UCB Fall 2009Review: Locks using test&set•Can we build test&set locks without busy-waiting?–Can’t entirely, but can minimize!–Idea: only busy-wait to atomically check lock value•Note: sleep has to be sure to reset the guard variable–Why can’t we do it just before or just after the sleep?Release() {// Short busy-wait timewhile (test&set(guard));if anyone on wait queue {take thread off wait queuePlace on ready queue;} else {value = FREE;}guard = 0;int guard = 0;int value = FREE;Acquire() {// Short busy-wait timewhile (test&set(guard));if (value == BUSY) {put thread on wait queue;go to sleep() & guard = 0;} else {value = BUSY;guard = 0;}}Lec 8.59/23/09 Kubiatowicz CS162 ©UCB Fall 2009Review: Semaphores•Definition: a Semaphore has a non-negative integer value and supports the following two operations:–P(): an atomic operation that waits for semaphore to become positive, then decrements it by 1 »Think of this as the wait() operation–V(): an atomic operation that increments the semaphore by 1, waking up a waiting P, if any»This of this as the signal() operation–Only time can set integer directly is at initialization time•Semaphore from railway analogy–Here is a semaphore initialized to 2 for resource control:Value=2Value=1Value=0Value=1Value=0Value=2Lec 8.69/23/09 Kubiatowicz CS162 ©UCB Fall 2009Goals for Today•Continue with Synchronization Abstractions–Monitors and condition variables•Readers-Writers problem and solutoin•Language Support for SynchronizationNote: Some slides and/or pictures in the following areadapted from slides ©2005 Silberschatz, Galvin, and Gagne Note: Some slides and/or pictures in the following areadapted from slides ©2005 Silberschatz, Galvin, and Gagne. Many slides generated from my lecture notes by Kubiatowicz.Lec 8.79/23/09 Kubiatowicz CS162 ©UCB Fall 2009Review: Full Solution to Bounded BufferSemaphore fullBuffer = 0; // Initially, no cokeSemaphore emptyBuffers = numBuffers;// Initially, num empty slotsSemaphore mutex = 1; // No one using machineProducer(item) {emptyBuffers.P(); // Wait until spacemutex.P(); // Wait until buffer freeEnqueue(item);mutex.V();fullBuffers.V(); // Tell consumers there is// more coke}Consumer() {fullBuffers.P(); // Check if there’s a cokemutex.P(); // Wait until machine freeitem = Dequeue();mutex.V();emptyBuffers.V(); // tell producer need morereturn item;}Lec 8.89/23/09 Kubiatowicz CS162 ©UCB Fall 2009Discussion about Solution•Why asymmetry?–Producer does: emptyBuffer.P(), fullBuffer.V()–Consumer does: fullBuffer.P(), emptyBuffer.V()•Is order of P’s important?–Yes! Can cause deadlock:Producer(item) {mutex.P(); // Wait until buffer freeemptyBuffers.P(); // Could wait forever!Enqueue(item);mutex.V();fullBuffers.V(); // Tell consumers more coke}•Is order of V’s important?–No, except that it might affect scheduling efficiency•What if we have 2 producers or 2 consumers?–Do we need to change anything?Lec 8.99/23/09 Kubiatowicz CS162 ©UCB Fall 2009Motivation for Monitors and Condition Variables•Semaphores are a huge step up, but:–They are confusing because they are dual purpose:»Both mutual exclusion and scheduling constraints»Example: the fact that flipping of P’s in bounded buffer gives deadlock is not immediately obvious–Cleaner idea: Use locks for mutual exclusion and condition variables for scheduling constraints•Definition: Monitor: a lock and zero or more condition variables for managing concurrent access to shared data–Use of Monitors is a programming paradigm–Some languages like Java provide monitors in the language•The lock provides mutual exclusion to shared data:–Always acquire before accessing shared data structure–Always release after finishing with shared data–Lock initially freeLec 8.109/23/09 Kubiatowicz CS162 ©UCB Fall 2009Simple Monitor Example (version 1)•Here is an (infinite) synchronized queueLock lock;Queue queue;AddToQueue(item) {lock.Acquire(); // Lock shared dataqueue.enqueue(item); // Add itemlock.Release(); // Release Lock}RemoveFromQueue() {lock.Acquire(); // Lock shared dataitem = queue.dequeue();// Get next item or nulllock.Release(); // Release Lockreturn(item); // Might return
View Full Document