59
Monitors, Condition Variables, and Readers-Writers Sarah Diesburg Operating Systems COP 4610

Monitors, Condition Variables, and Readers-Writers

  • Upload
    devona

  • View
    39

  • Download
    0

Embed Size (px)

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

Citation preview

Page 1: Monitors, Condition Variables, and Readers-Writers

Monitors, Condition Variables, and Readers-Writers

Sarah DiesburgOperating Systems

COP 4610

Page 2: 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 scheduling

• The idea of monitors is to separate these two concerns

Page 3: Monitors, Condition Variables, and Readers-Writers

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

Page 4: Monitors, Condition Variables, and Readers-Writers

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

Page 5: Monitors, Condition Variables, and Readers-Writers

More on Locks

• Always acquire a lock before accessing a shared data structure

• Always release the lock after finishing with the shared data structure

Page 6: Monitors, Condition Variables, and Readers-Writers

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;

}

Page 7: Monitors, Condition Variables, and Readers-Writers

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

Page 8: Monitors, Condition Variables, and Readers-Writers

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

Page 9: Monitors, Condition Variables, and Readers-Writers

Condition Variables

• Note – The three operations can only be used inside

locked regions

Page 10: Monitors, Condition Variables, and Readers-Writers

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;

}

Page 11: Monitors, Condition Variables, and Readers-Writers

Hoare vs. Mesa Monitors

• Hoare Monitors (used in most textbooks)– Signal() transfers the CPU directly to a waiting

thread

Page 12: Monitors, Condition Variables, and Readers-Writers

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

Page 13: Monitors, Condition Variables, and Readers-Writers

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

Page 14: Monitors, Condition Variables, and Readers-Writers

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

Page 15: Monitors, Condition Variables, and Readers-Writers

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

Page 16: Monitors, Condition Variables, and Readers-Writers

Developing the Solution

• Global states:

activeReaders = 0;

activeWriters = 0;

waitingReaders = 0;

waitingWriters = 0;

Condition okToRead = NULL;

Condition okToWrite = NULL;

Lock lock = FREE;

Page 17: Monitors, Condition Variables, and Readers-Writers

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();

}

Page 18: Monitors, Condition Variables, and Readers-Writers

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();

}

Page 19: Monitors, Condition Variables, and Readers-Writers

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();

}

Page 20: Monitors, Condition Variables, and Readers-Writers

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();

}

Page 21: Monitors, Condition Variables, and Readers-Writers

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();

}

Page 22: Monitors, Condition Variables, and Readers-Writers

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();

}

Page 23: Monitors, Condition Variables, and Readers-Writers

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();

}

Page 24: Monitors, Condition Variables, and Readers-Writers

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();

}

Page 25: Monitors, Condition Variables, and Readers-Writers

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();

}

Page 26: Monitors, Condition Variables, and Readers-Writers

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();

}

Page 27: Monitors, Condition Variables, and Readers-Writers

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();

}

Page 28: Monitors, Condition Variables, and Readers-Writers

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();

}

Page 29: Monitors, Condition Variables, and Readers-Writers

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();

}

Page 30: Monitors, Condition Variables, and Readers-Writers

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();

}

Page 31: Monitors, Condition Variables, and Readers-Writers

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();

}

Page 32: Monitors, Condition Variables, and Readers-Writers

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();

}

Page 33: Monitors, Condition Variables, and Readers-Writers

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();

}

Page 34: Monitors, Condition Variables, and Readers-Writers

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();

}

Page 35: Monitors, Condition Variables, and Readers-Writers

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();

}

Page 36: Monitors, Condition Variables, and Readers-Writers

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();

}

Page 37: Monitors, Condition Variables, and Readers-Writers

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();

}

Page 38: Monitors, Condition Variables, and Readers-Writers

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();

}

Page 39: Monitors, Condition Variables, and Readers-Writers

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();

}

Page 40: Monitors, Condition Variables, and Readers-Writers

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();

}

Page 41: Monitors, Condition Variables, and Readers-Writers

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();

}

Page 42: Monitors, Condition Variables, and Readers-Writers

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();

}

Page 43: Monitors, Condition Variables, and Readers-Writers

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();

}

Page 44: Monitors, Condition Variables, and Readers-Writers

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();

}

Page 45: Monitors, Condition Variables, and Readers-Writers

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();

}

Page 46: Monitors, Condition Variables, and Readers-Writers

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();

}

Page 47: Monitors, Condition Variables, and Readers-Writers

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();

}

Page 48: Monitors, Condition Variables, and Readers-Writers

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();

}

Page 49: Monitors, Condition Variables, and Readers-Writers

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();

}

Page 50: Monitors, Condition Variables, and Readers-Writers

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();

}

Page 51: Monitors, Condition Variables, and Readers-Writers

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();

}

Page 52: Monitors, Condition Variables, and Readers-Writers

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();

}

Page 53: Monitors, Condition Variables, and Readers-Writers

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();

}

Page 54: Monitors, Condition Variables, and Readers-Writers

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();

}

Page 55: Monitors, Condition Variables, and Readers-Writers

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();

}

Page 56: Monitors, Condition Variables, and Readers-Writers

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();

}

Page 57: Monitors, Condition Variables, and Readers-Writers

Semaphores vs. Monitors

• Can we implement monitors with semaphores?Wait() {

P(s);

}

Signal() {

V(s);

}

Page 58: Monitors, Condition Variables, and Readers-Writers

Semaphores vs. Monitors

• Not quite…• Condition variables only work inside a lock– Using semaphores inside a lock may deadlock

Page 59: Monitors, Condition Variables, and Readers-Writers

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