Monitors, Condition Variables, and Readers-Writers
590 likes | 767 Vues
Monitors, Condition Variables, and Readers-Writers. Motivation for Monitors. Semaphores are a big step from the low-level loads and stores However, semaphores are used for both mutual exclusion and synchronization The idea of monitors is to separate these two concerns. Monitor Defined.
Monitors, Condition Variables, and Readers-Writers
E N D
Presentation Transcript
Motivation for Monitors • Semaphores are a big step from the low-level loads and stores • However, semaphores are used for both mutual exclusion and synchronization • The idea of monitors is to separate these two concerns
Monitor Defined • Monitor: a lock + condition variables • Lock: provides mutual exclusion to shared data • Condition variable: provides a queue for waiting threads inside a critical section • Enabling synchronization between processes.
Locks • A lock provides two operations: • Lock::Acquire() • Wait until the lock is free, then grab it • Lock::Release() • Unlock, wake up anyone waiting to Acquire • A lock is initially free
More on Locks • Always acquire a lock before accessing a shared data structure • Always release the lock after finishing with the shared data structure
An Example of Using Locks AddToQueue() { Lock.Acquire(); // put 1 item to the queue Lock.Release(); } RemoveFromQueue() { Lock.Acquire(); // if something on the queue // remove 1 item form the queue Lock.Release(); return item; }
Condition Variables • We need additional mechanisms to wait inside locked regions • However, holding the lock while waiting prevents other threads from entering the locked region • Condition variables make it possible to sleep inside a critical section • Atomically release the lock & go to sleep
Condition Variables • Each condition variable • Consists of a queue of threads • Provides three operations • Wait(); • Atomically release the lock and go to sleep • Reacquire lock on return • Signal(); • Wake up one waiting thread, if any • Broadcast(); • Wake up all waiting threads
Condition Variables • Note • The three operations can only be used inside locked regions
An Example of Using Condition Variables AddToQueue() { lock.Acquire(); // put 1 item to the queue condition.Signal(&lock); lock.Release(); } RemoveFromQueue() { lock.Acquire(); while nothing on queue condition.Wait(&lock); lock.Release(); return item; }
Hoare vs. Mesa Monitors • Hoare Monitors (used in most textbooks) • Signal() transfers the CPU directly to a waiting thread
Mesa vs. Hoare Monitors • Mesa Monitors (used in most real operating systems) • Signal() only puts a waiting thread on the scheduler’s ready queue • By the time the waken thread gets the CPU, the waiting condition may no longer be true and needs to be retested
Readers-Writers Problem • Commonly seen in database applications • Readers never modify the database • Writers read and modify the database • We want one writer at a time, but many readers at the same time
Constraints • A reader should wait when a writer is accessing or waiting for the database • Condition okToRead • A write should wait when there is a reader or writer accessing the database • Condition okToWrite • A reader or a writer should wait when someone is modifying global states • Lock lock
Basic Structure of the Solution • Reader • Wait until no writers • Access database • Wake up waiting writers • Writer • Wait until no active readers or writers • Access database • Wake up waiting readers or writers
Developing the Solution • Global states: activeReaders = 0; activeWriters = 0; waitingReaders = 0; waitingWriters = 0; Condition okToRead = NULL; Condition okToWrite = NULL; Lock lock = FREE;
Reader() { lock.Acquire(); ++activeReaders; lock.Release(); // access database lock.Acquire(); --activeReaders; lock.Release(); } Writer() { lock.Acquire(); ++activeWriters; lock.Release(); // access database lock.Acquire(); --activeWriters; lock.Release(); } Put in Locks and Some Global States
Reader() { lock.Acquire(); while (activeWriters > 0 || waitingWriters > 0) { ++waitingReaders; okToRead.Wait(&lock); --waitingReaders; } ++activeReaders; lock.Release(); // access database lock.Acquire(); --activeReaders; lock.Release(); } Writer() { lock.Acquire(); ++activeWriters; lock.Release(); // access database lock.Acquire(); --activeWriters; lock.Release(); } Add the Wait Condition for Reader
Reader() { lock.Acquire(); while (activeWriters > 0 || waitingWriters > 0) { ++waitingReaders; okToRead.Wait(&lock); --waitingReaders; } ++activeReaders; lock.Release(); // access database lock.Acquire(); --activeReaders; lock.Release(); } Writer() { lock.Acquire(); while (activeWriters > 0 || activeReaders > 0) { ++waitingWriters; okToWrite.Wait(&lock); --waitingWriters; } ++activeWriters; lock.Release(); // access database lock.Acquire(); --activeWriters; lock.Release(); } Add the Wait Condition for Writer
Reader() { lock.Acquire(); while (activeWriters > 0 || waitingWriters > 0) { ++waitingReaders; okToRead.Wait(&lock); --waitingReaders; } ++activeReaders; lock.Release(); // access database lock.Acquire(); --activeReaders; if (activeReaders == 0 && waitingWriters > 0) { okToWrite.Signal(&lock); } lock.Release(); } Writer() { lock.Acquire(); while (activeWriters > 0 || activeReaders > 0) { ++waitingWriters; okToWrite.Wait(&lock); --waitingWriters; } ++activeWriters; lock.Release(); // access database lock.Acquire(); --activeWriters; lock.Release(); } Add the Signal Condition for Reader
Reader() { lock.Acquire(); while (activeWriters > 0 || waitingWriters > 0) { ++waitingReaders; okToRead.Wait(&lock); --waitingReaders; } ++activeReaders; lock.Release(); // access database lock.Acquire(); --activeReaders; if (activeReaders == 0 && waitingWriters > 0) { okToWrite.Signal(&lock); } lock.Release(); } Writer() { lock.Acquire(); while (activeWriters > 0 || activeReaders > 0) { ++waitingWriters; okToWrite.Wait(&lock); --waitingWriters; } ++activeWriters; lock.Release(); // access database lock.Acquire(); --activeWriters; if (waitingWriters > 0) { okToWrite.Signal(&lock); } else if (waitingReaders > 0) { okToRead.Broadcast(&lock); } lock.Release(); } Add the Signal Condition for Writer
Reader() { lock.Acquire(); while (activeWriters > 0 || waitingWriters > 0) { ++waitingReaders; okToRead.Wait(&lock); --waitingReaders; } ++activeReaders; lock.Release(); // access database lock.Acquire(); --activeReaders; if (activeReaders == 0 && waitingWriters > 0) { okToWrite.Signal(&lock); } lock.Release(); } Writer() { lock.Acquire(); while (activeWriters > 0 || activeReaders > 0) { ++waitingWriters; okToWrite.Wait(&lock); --waitingWriters; } ++activeWriters; lock.Release(); // access database lock.Acquire(); --activeWriters; if (waitingWriters > 0) { okToWrite.Signal(&lock); } else if (waitingReaders > 0) { okToRead.Broadcast(&lock); } lock.Release(); } Code Demonstration
Reader() { lock.Acquire(); while (activeWriters > 0 || waitingWriters > 0) { ++waitingReaders; okToRead.Wait(&lock); --waitingReaders; } ++activeReaders; lock.Release(); // access database lock.Acquire(); --activeReaders; if (activeReaders == 0 && waitingWriters > 0) { okToWrite.Signal(&lock); } lock.Release(); } Writer() { lock.Acquire(); while (activeWriters > 0 || activeReaders > 0) { ++waitingWriters; okToWrite.Wait(&lock); --waitingWriters; } ++activeWriters; lock.Release(); // access database lock.Acquire(); --activeWriters; if (waitingWriters > 0) { okToWrite.Signal(&lock); } else if (waitingReaders > 0) { okToRead.Broadcast(&lock); } lock.Release(); } Code Demonstration
Reader() { lock.Acquire(); while (activeWriters > 0 || waitingWriters > 0) { ++waitingReaders; okToRead.Wait(&lock); --waitingReaders; } ++activeReaders; lock.Release(); // access database lock.Acquire(); --activeReaders; if (activeReaders == 0 && waitingWriters > 0) { okToWrite.Signal(&lock); } lock.Release(); } Writer() { lock.Acquire(); while (activeWriters > 0 || activeReaders > 0) { ++waitingWriters; okToWrite.Wait(&lock); --waitingWriters; } ++activeWriters; lock.Release(); // access database lock.Acquire(); --activeWriters; if (waitingWriters > 0) { okToWrite.Signal(&lock); } else if (waitingReaders > 0) { okToRead.Broadcast(&lock); } lock.Release(); } Code Demonstration
Reader() { lock.Acquire(); while (activeWriters > 0 || waitingWriters > 0) { ++waitingReaders; okToRead.Wait(&lock); --waitingReaders; } ++activeReaders; lock.Release(); // access database lock.Acquire(); --activeReaders; if (activeReaders == 0 && waitingWriters > 0) { okToWrite.Signal(&lock); } lock.Release(); } Writer() { lock.Acquire(); while (activeWriters > 0 || activeReaders > 0) { ++waitingWriters; okToWrite.Wait(&lock); --waitingWriters; } ++activeWriters; lock.Release(); // access database lock.Acquire(); --activeWriters; if (waitingWriters > 0) { okToWrite.Signal(&lock); } else if (waitingReaders > 0) { okToRead.Broadcast(&lock); } lock.Release(); } Code Demonstration
Reader() { lock.Acquire(); while (activeWriters > 0 || waitingWriters > 0) { ++waitingReaders; okToRead.Wait(&lock); --waitingReaders; } ++activeReaders; lock.Release(); // access database lock.Acquire(); --activeReaders; if (activeReaders == 0 && waitingWriters > 0) { okToWrite.Signal(&lock); } lock.Release(); } Writer() { lock.Acquire(); while (activeWriters > 0 || activeReaders > 0) { ++waitingWriters; okToWrite.Wait(&lock); --waitingWriters; } ++activeWriters; lock.Release(); // access database lock.Acquire(); --activeWriters; if (waitingWriters > 0) { okToWrite.Signal(&lock); } else if (waitingReaders > 0) { okToRead.Broadcast(&lock); } lock.Release(); } Code Demonstration
Reader() { lock.Acquire(); while (activeWriters > 0 || waitingWriters > 0) { ++waitingReaders; okToRead.Wait(&lock); --waitingReaders; } ++activeReaders; lock.Release(); // access database lock.Acquire(); --activeReaders; if (activeReaders == 0 && waitingWriters > 0) { okToWrite.Signal(&lock); } lock.Release(); } Writer() { lock.Acquire(); while (activeWriters > 0 || activeReaders > 0) { ++waitingWriters; okToWrite.Wait(&lock); --waitingWriters; } ++activeWriters; lock.Release(); // access database lock.Acquire(); --activeWriters; if (waitingWriters > 0) { okToWrite.Signal(&lock); } else if (waitingReaders > 0) { okToRead.Broadcast(&lock); } lock.Release(); } Code Demonstration
Reader() { lock.Acquire(); while (activeWriters > 0 || waitingWriters > 0) { ++waitingReaders; okToRead.Wait(&lock); --waitingReaders; } ++activeReaders; lock.Release(); // access database lock.Acquire(); --activeReaders; if (activeReaders == 0 && waitingWriters > 0) { okToWrite.Signal(&lock); } lock.Release(); } Writer() { lock.Acquire(); while (activeWriters > 0 || activeReaders > 0) { ++waitingWriters; okToWrite.Wait(&lock); --waitingWriters; } ++activeWriters; lock.Release(); // access database lock.Acquire(); --activeWriters; if (waitingWriters > 0) { okToWrite.Signal(&lock); } else if (waitingReaders > 0) { okToRead.Broadcast(&lock); } lock.Release(); } Code Demonstration
Reader() { lock.Acquire(); while (activeWriters > 0 || waitingWriters > 0) { ++waitingReaders; okToRead.Wait(&lock); --waitingReaders; } ++activeReaders; lock.Release(); // access database lock.Acquire(); --activeReaders; if (activeReaders == 0 && waitingWriters > 0) { okToWrite.Signal(&lock); } lock.Release(); } Writer() { lock.Acquire(); while (activeWriters > 0 || activeReaders > 0) { ++waitingWriters; okToWrite.Wait(&lock); --waitingWriters; } ++activeWriters; lock.Release(); // access database lock.Acquire(); --activeWriters; if (waitingWriters > 0) { okToWrite.Signal(&lock); } else if (waitingReaders > 0) { okToRead.Broadcast(&lock); } lock.Release(); } Code Demonstration
Reader() { lock.Acquire(); while (activeWriters > 0 || waitingWriters > 0) { ++waitingReaders; okToRead.Wait(&lock); --waitingReaders; } ++activeReaders; lock.Release(); // access database lock.Acquire(); --activeReaders; if (activeReaders == 0 && waitingWriters > 0) { okToWrite.Signal(&lock); } lock.Release(); } Writer() { lock.Acquire(); while (activeWriters > 0 || activeReaders > 0) { ++waitingWriters; okToWrite.Wait(&lock); --waitingWriters; } ++activeWriters; lock.Release(); // access database lock.Acquire(); --activeWriters; if (waitingWriters > 0) { okToWrite.Signal(&lock); } else if (waitingReaders > 0) { okToRead.Broadcast(&lock); } lock.Release(); } Code Demonstration
Reader() { lock.Acquire(); while (activeWriters > 0 || waitingWriters > 0) { ++waitingReaders; okToRead.Wait(&lock); --waitingReaders; } ++activeReaders; lock.Release(); // access database lock.Acquire(); --activeReaders; if (activeReaders == 0 && waitingWriters > 0) { okToWrite.Signal(&lock); } lock.Release(); } Writer() { lock.Acquire(); while (activeWriters > 0 || activeReaders > 0) { ++waitingWriters; okToWrite.Wait(&lock); --waitingWriters; } ++activeWriters; lock.Release(); // access database lock.Acquire(); --activeWriters; if (waitingWriters > 0) { okToWrite.Signal(&lock); } else if (waitingReaders > 0) { okToRead.Broadcast(&lock); } lock.Release(); } Code Demonstration
Reader() { lock.Acquire(); while (activeWriters > 0 || waitingWriters > 0) { ++waitingReaders; okToRead.Wait(&lock); --waitingReaders; } ++activeReaders; lock.Release(); // access database lock.Acquire(); --activeReaders; if (activeReaders == 0 && waitingWriters > 0) { okToWrite.Signal(&lock); } lock.Release(); } Writer() { lock.Acquire(); while (activeWriters > 0 || activeReaders > 0) { ++waitingWriters; okToWrite.Wait(&lock); --waitingWriters; } ++activeWriters; lock.Release(); // access database lock.Acquire(); --activeWriters; if (waitingWriters > 0) { okToWrite.Signal(&lock); } else if (waitingReaders > 0) { okToRead.Broadcast(&lock); } lock.Release(); } Code Demonstration
Reader() { lock.Acquire(); while (activeWriters > 0 || waitingWriters > 0) { ++waitingReaders; okToRead.Wait(&lock); --waitingReaders; } ++activeReaders; lock.Release(); // access database lock.Acquire(); --activeReaders; if (activeReaders == 0 && waitingWriters > 0) { okToWrite.Signal(&lock); } lock.Release(); } Writer() { lock.Acquire(); while (activeWriters > 0 || activeReaders > 0) { ++waitingWriters; okToWrite.Wait(&lock); --waitingWriters; } ++activeWriters; lock.Release(); // access database lock.Acquire(); --activeWriters; if (waitingWriters > 0) { okToWrite.Signal(&lock); } else if (waitingReaders > 0) { okToRead.Broadcast(&lock); } lock.Release(); } Code Demonstration
Reader() { lock.Acquire(); while (activeWriters > 0 || waitingWriters > 0) { ++waitingReaders; okToRead.Wait(&lock); --waitingReaders; } ++activeReaders; lock.Release(); // access database lock.Acquire(); --activeReaders; if (activeReaders == 0 && waitingWriters > 0) { okToWrite.Signal(&lock); } lock.Release(); } Writer() { lock.Acquire(); while (activeWriters > 0 || activeReaders > 0) { ++waitingWriters; okToWrite.Wait(&lock); --waitingWriters; } ++activeWriters; lock.Release(); // access database lock.Acquire(); --activeWriters; if (waitingWriters > 0) { okToWrite.Signal(&lock); } else if (waitingReaders > 0) { okToRead.Broadcast(&lock); } lock.Release(); } Code Demonstration
Reader() { lock.Acquire(); while (activeWriters > 0 || waitingWriters > 0) { ++waitingReaders; okToRead.Wait(&lock); --waitingReaders; } ++activeReaders; lock.Release(); // access database lock.Acquire(); --activeReaders; if (activeReaders == 0 && waitingWriters > 0) { okToWrite.Signal(&lock); } lock.Release(); } Writer() { lock.Acquire(); while (activeWriters > 0 || activeReaders > 0) { ++waitingWriters; okToWrite.Wait(&lock); --waitingWriters; } ++activeWriters; lock.Release(); // access database lock.Acquire(); --activeWriters; if (waitingWriters > 0) { okToWrite.Signal(&lock); } else if (waitingReaders > 0) { okToRead.Broadcast(&lock); } lock.Release(); } Code Demonstration
Reader() { lock.Acquire(); while (activeWriters > 0 || waitingWriters > 0) { ++waitingReaders; okToRead.Wait(&lock); --waitingReaders; } ++activeReaders; lock.Release(); // access database lock.Acquire(); --activeReaders; if (activeReaders == 0 && waitingWriters > 0) { okToWrite.Signal(&lock); } lock.Release(); } Writer() { lock.Acquire(); while (activeWriters > 0 || activeReaders > 0) { ++waitingWriters; okToWrite.Wait(&lock); --waitingWriters; } ++activeWriters; lock.Release(); // access database lock.Acquire(); --activeWriters; if (waitingWriters > 0) { okToWrite.Signal(&lock); } else if (waitingReaders > 0) { okToRead.Broadcast(&lock); } lock.Release(); } Code Demonstration
Reader() { lock.Acquire(); while (activeWriters > 0 || waitingWriters > 0) { ++waitingReaders; okToRead.Wait(&lock); --waitingReaders; } ++activeReaders; lock.Release(); // access database lock.Acquire(); --activeReaders; if (activeReaders == 0 && waitingWriters > 0) { okToWrite.Signal(&lock); } lock.Release(); } Writer() { lock.Acquire(); while (activeWriters > 0 || activeReaders > 0) { ++waitingWriters; okToWrite.Wait(&lock); --waitingWriters; } ++activeWriters; lock.Release(); // access database lock.Acquire(); --activeWriters; if (waitingWriters > 0) { okToWrite.Signal(&lock); } else if (waitingReaders > 0) { okToRead.Broadcast(&lock); } lock.Release(); } Code Demonstration
Reader() { lock.Acquire(); while (activeWriters > 0 || waitingWriters > 0) { ++waitingReaders; okToRead.Wait(&lock); --waitingReaders; } ++activeReaders; lock.Release(); // access database lock.Acquire(); --activeReaders; if (activeReaders == 0 && waitingWriters > 0) { okToWrite.Signal(&lock); } lock.Release(); } Writer() { lock.Acquire(); while (activeWriters > 0 || activeReaders > 0) { ++waitingWriters; okToWrite.Wait(&lock); --waitingWriters; } ++activeWriters; lock.Release(); // access database lock.Acquire(); --activeWriters; if (waitingWriters > 0) { okToWrite.Signal(&lock); } else if (waitingReaders > 0) { okToRead.Broadcast(&lock); } lock.Release(); } Code Demonstration
Reader() { lock.Acquire(); while (activeWriters > 0 || waitingWriters > 0) { ++waitingReaders; okToRead.Wait(&lock); --waitingReaders; } ++activeReaders; lock.Release(); // access database lock.Acquire(); --activeReaders; if (activeReaders == 0 && waitingWriters > 0) { okToWrite.Signal(&lock); } lock.Release(); } Writer() { lock.Acquire(); while (activeWriters > 0 || activeReaders > 0) { ++waitingWriters; okToWrite.Wait(&lock); --waitingWriters; } ++activeWriters; lock.Release(); // access database lock.Acquire(); --activeWriters; if (waitingWriters > 0) { okToWrite.Signal(&lock); } else if (waitingReaders > 0) { okToRead.Broadcast(&lock); } lock.Release(); } Code Demonstration
Reader() { lock.Acquire(); while (activeWriters > 0 || waitingWriters > 0) { ++waitingReaders; okToRead.Wait(&lock); --waitingReaders; } ++activeReaders; lock.Release(); // access database lock.Acquire(); --activeReaders; if (activeReaders == 0 && waitingWriters > 0) { okToWrite.Signal(&lock); } lock.Release(); } Writer() { lock.Acquire(); while (activeWriters > 0 || activeReaders > 0) { ++waitingWriters; okToWrite.Wait(&lock); --waitingWriters; } ++activeWriters; lock.Release(); // access database lock.Acquire(); --activeWriters; if (waitingWriters > 0) { okToWrite.Signal(&lock); } else if (waitingReaders > 0) { okToRead.Broadcast(&lock); } lock.Release(); } Code Demonstration
Reader() { lock.Acquire(); while (activeWriters > 0 || waitingWriters > 0) { ++waitingReaders; okToRead.Wait(&lock); --waitingReaders; } ++activeReaders; lock.Release(); // access database lock.Acquire(); --activeReaders; if (activeReaders == 0 && waitingWriters > 0) { okToWrite.Signal(&lock); } lock.Release(); } Writer() { lock.Acquire(); while (activeWriters > 0 || activeReaders > 0) { ++waitingWriters; okToWrite.Wait(&lock); --waitingWriters; } ++activeWriters; lock.Release(); // access database lock.Acquire(); --activeWriters; if (waitingWriters > 0) { okToWrite.Signal(&lock); } else if (waitingReaders > 0) { okToRead.Broadcast(&lock); } lock.Release(); } Code Demonstration
Reader() { lock.Acquire(); while (activeWriters > 0 || waitingWriters > 0) { ++waitingReaders; okToRead.Wait(&lock); --waitingReaders; } ++activeReaders; lock.Release(); // access database lock.Acquire(); --activeReaders; if (activeReaders == 0 && waitingWriters > 0) { okToWrite.Signal(&lock); } lock.Release(); } Writer() { lock.Acquire(); while (activeWriters > 0 || activeReaders > 0) { ++waitingWriters; okToWrite.Wait(&lock); --waitingWriters; } ++activeWriters; lock.Release(); // access database lock.Acquire(); --activeWriters; if (waitingWriters > 0) { okToWrite.Signal(&lock); } else if (waitingReaders > 0) { okToRead.Broadcast(&lock); } lock.Release(); } Code Demonstration
Reader() { lock.Acquire(); while (activeWriters > 0 || waitingWriters > 0) { ++waitingReaders; okToRead.Wait(&lock); --waitingReaders; } ++activeReaders; lock.Release(); // access database lock.Acquire(); --activeReaders; if (activeReaders == 0 && waitingWriters > 0) { okToWrite.Signal(&lock); } lock.Release(); } Writer() { lock.Acquire(); while (activeWriters > 0 || activeReaders > 0) { ++waitingWriters; okToWrite.Wait(&lock); --waitingWriters; } ++activeWriters; lock.Release(); // access database lock.Acquire(); --activeWriters; if (waitingWriters > 0) { okToWrite.Signal(&lock); } else if (waitingReaders > 0) { okToRead.Broadcast(&lock); } lock.Release(); } Code Demonstration
Reader() { lock.Acquire(); while (activeWriters > 0 || waitingWriters > 0) { ++waitingReaders; okToRead.Wait(&lock); --waitingReaders; } ++activeReaders; lock.Release(); // access database lock.Acquire(); --activeReaders; if (activeReaders == 0 && waitingWriters > 0) { okToWrite.Signal(&lock); } lock.Release(); } Writer() { lock.Acquire(); while (activeWriters > 0 || activeReaders > 0) { ++waitingWriters; okToWrite.Wait(&lock); --waitingWriters; } ++activeWriters; lock.Release(); // access database lock.Acquire(); --activeWriters; if (waitingWriters > 0) { okToWrite.Signal(&lock); } else if (waitingReaders > 0) { okToRead.Broadcast(&lock); } lock.Release(); } Code Demonstration
Reader() { lock.Acquire(); while (activeWriters > 0 || waitingWriters > 0) { ++waitingReaders; okToRead.Wait(&lock); --waitingReaders; } ++activeReaders; lock.Release(); // access database lock.Acquire(); --activeReaders; if (activeReaders == 0 && waitingWriters > 0) { okToWrite.Signal(&lock); } lock.Release(); } Writer() { lock.Acquire(); while (activeWriters > 0 || activeReaders > 0) { ++waitingWriters; okToWrite.Wait(&lock); --waitingWriters; } ++activeWriters; lock.Release(); // access database lock.Acquire(); --activeWriters; if (waitingWriters > 0) { okToWrite.Signal(&lock); } else if (waitingReaders > 0) { okToRead.Broadcast(&lock); } lock.Release(); } Code Demonstration
Reader() { lock.Acquire(); while (activeWriters > 0 || waitingWriters > 0) { ++waitingReaders; okToRead.Wait(&lock); --waitingReaders; } ++activeReaders; lock.Release(); // access database lock.Acquire(); --activeReaders; if (activeReaders == 0 && waitingWriters > 0) { okToWrite.Signal(&lock); } lock.Release(); } Writer() { lock.Acquire(); while (activeWriters > 0 || activeReaders > 0) { ++waitingWriters; okToWrite.Wait(&lock); --waitingWriters; } ++activeWriters; lock.Release(); // access database lock.Acquire(); --activeWriters; if (waitingWriters > 0) { okToWrite.Signal(&lock); } else if (waitingReaders > 0) { okToRead.Broadcast(&lock); } lock.Release(); } Code Demonstration
Reader() { lock.Acquire(); while (activeWriters > 0 || waitingWriters > 0) { ++waitingReaders; okToRead.Wait(&lock); --waitingReaders; } ++activeReaders; lock.Release(); // access database lock.Acquire(); --activeReaders; if (activeReaders == 0 && waitingWriters > 0) { okToWrite.Signal(&lock); } lock.Release(); } Writer() { lock.Acquire(); while (activeWriters > 0 || activeReaders > 0) { ++waitingWriters; okToWrite.Wait(&lock); --waitingWriters; } ++activeWriters; lock.Release(); // access database lock.Acquire(); --activeWriters; if (waitingWriters > 0) { okToWrite.Signal(&lock); } else if (waitingReaders > 0) { okToRead.Broadcast(&lock); } lock.Release(); } Code Demonstration
Reader() { lock.Acquire(); while (activeWriters > 0 || waitingWriters > 0) { ++waitingReaders; okToRead.Wait(&lock); --waitingReaders; } ++activeReaders; lock.Release(); // access database lock.Acquire(); --activeReaders; if (activeReaders == 0 && waitingWriters > 0) { okToWrite.Signal(&lock); } lock.Release(); } Writer() { lock.Acquire(); while (activeWriters > 0 || activeReaders > 0) { ++waitingWriters; okToWrite.Wait(&lock); --waitingWriters; } ++activeWriters; lock.Release(); // access database lock.Acquire(); --activeWriters; if (waitingWriters > 0) { okToWrite.Signal(&lock); } else if (waitingReaders > 0) { okToRead.Broadcast(&lock); } lock.Release(); } Code Demonstration
Reader() { lock.Acquire(); while (activeWriters > 0 || waitingWriters > 0) { ++waitingReaders; okToRead.Wait(&lock); --waitingReaders; } ++activeReaders; lock.Release(); // access database lock.Acquire(); --activeReaders; if (activeReaders == 0 && waitingWriters > 0) { okToWrite.Signal(&lock); } lock.Release(); } Writer() { lock.Acquire(); while (activeWriters > 0 || activeReaders > 0) { ++waitingWriters; okToWrite.Wait(&lock); --waitingWriters; } ++activeWriters; lock.Release(); // access database lock.Acquire(); --activeWriters; if (waitingWriters > 0) { okToWrite.Signal(&lock); } else if (waitingReaders > 0) { okToRead.Broadcast(&lock); } lock.Release(); } Code Demonstration
Reader() { lock.Acquire(); while (activeWriters > 0 || waitingWriters > 0) { ++waitingReaders; okToRead.Wait(&lock); --waitingReaders; } ++activeReaders; lock.Release(); // access database lock.Acquire(); --activeReaders; if (activeReaders == 0 && waitingWriters > 0) { okToWrite.Signal(&lock); } lock.Release(); } Writer() { lock.Acquire(); while (activeWriters > 0 || activeReaders > 0) { ++waitingWriters; okToWrite.Wait(&lock); --waitingWriters; } ++activeWriters; lock.Release(); // access database lock.Acquire(); --activeWriters; if (waitingWriters > 0) { okToWrite.Signal(&lock); } else if (waitingReaders > 0) { okToRead.Broadcast(&lock); } lock.Release(); } Code Demonstration