600 likes | 619 Views
Learn about monitors, condition variables, and how they are used to solve the readers-writers problem. Understand the concepts, operations, and examples of using locks and condition variables in multi-threaded applications.
E N D
Monitors, Condition Variables, and Readers-Writers Andy Wang Operating Systems COP 4610 / CGS 5765
Motivation for Monitors • Semaphores are a big step from the low-level loads and stores • However, semaphores are used for both mutual exclusion and scheduling • 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
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 AddToBuffer() { Lock.Acquire(); // put 1 item to the buffer Lock.Release(); } RemoveFromBuffer() { Lock.Acquire(); // if something in the buffer // remove 1 item form the buffer 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 AddToBuffer() { lock.Acquire(); // put 1 item to the buffer condition.Broadcast(&lock); // move threads from the // wait queue to the ready queue // do something else lock.Release(); } RemoveFromBuffer() { lock.Acquire(); while nothing in the buffer { condition.Wait(&lock); // implicit lock release // implicit lock acquire } 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 writer 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