monitors, condition variables, and readers-writers
DESCRIPTION
Monitors, Condition Variables, and Readers-Writers. Sarah Diesburg Operating Systems COP 4610. 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 - PowerPoint PPT PresentationTRANSCRIPT
Monitors, Condition Variables, and Readers-Writers
Sarah DiesburgOperating Systems
COP 4610
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 LocksAddToBuffer() {
Lock.Acquire();// put 1 item to the bufferLock.Release();
}
RemoveFromBuffer() {Lock.Acquire();// if something in the buffer// remove 1 item form the bufferLock.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 buffercondition.Broadcast(&lock); // move threads from the // wait queue to the ready queue// do something elselock.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 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;
Put in Locks and Some Global States
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();
}
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();
++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;
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;
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 DemonstrationReader() {
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 DemonstrationReader() {
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 DemonstrationReader() {
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 DemonstrationReader() {
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 DemonstrationReader() {
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 DemonstrationReader() {
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 DemonstrationReader() {
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 DemonstrationReader() {
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 DemonstrationReader() {
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 DemonstrationReader() {
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 DemonstrationReader() {
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 DemonstrationReader() {
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 DemonstrationReader() {
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 DemonstrationReader() {
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 DemonstrationReader() {
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 DemonstrationReader() {
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 DemonstrationReader() {
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 DemonstrationReader() {
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 DemonstrationReader() {
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 DemonstrationReader() {
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 DemonstrationReader() {
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 DemonstrationReader() {
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 DemonstrationReader() {
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 DemonstrationReader() {
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 DemonstrationReader() {
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 DemonstrationReader() {
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 DemonstrationReader() {
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 DemonstrationReader() {
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 DemonstrationReader() {
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 DemonstrationReader() {
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 DemonstrationReader() {
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 DemonstrationReader() {
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 DemonstrationReader() {
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 DemonstrationReader() {
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 DemonstrationReader() {
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();
}
Semaphores vs. Monitors
• Can we implement monitors with semaphores?Wait() {
P(s);
}
Signal() {
V(s);
}
Semaphores vs. Monitors
• Not quite…• Condition variables only work inside a lock– Using semaphores inside a lock may deadlock
Semaphores vs. Monitors
• Condition variables have no history, but semaphores have– Signal() with an empty queue does nothing• A subsequent Wait() will wait
– V() increments semaphore• A subsequent P() will not wait