monitors, condition variables, and readers-writers

Post on 06-Jan-2016

39 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

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 Presentation

TRANSCRIPT

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

top related