410 likes | 558 Views
Operating Systems CMPSCI 377 Lecture 9: Synchronization III. Emery Berger University of Massachusetts, Amherst. Last Time: Locks & Semaphores. More on hardware support Implementing locks Test & Set Busy waiting Semaphores Generalization of locks. This Time: More Synch Primitives.
E N D
Operating SystemsCMPSCI 377Lecture 9: Synchronization III Emery Berger University of Massachusetts, Amherst
Last Time: Locks & Semaphores • More on hardware support • Implementing locks • Test & Set • Busy waiting • Semaphores • Generalization of locks
This Time: More Synch Primitives • Reader-Writer Locks • Monitors • Condition Variables
Reader/Writers Problem • Suppose one object shared among many threads • Each thread is either a reader or a writer • Readers – only read data, never modify • Writers – read & modify data • How should we control access to this object? • Which synchronization primitive? W R R W R
Single Lock thread A Lock.acquire() Read data Lock.release() • Drawbacks of this solution? thread B Lock.acquire() Modify data Lock.release() thread C Lock.acquire() Read data Lock.release() thread D Lock.acquire() Read data Lock.release() thread E Lock.acquire() Read data Lock.release() thread F Lock.acquire() Modify data Lock.release()
Readers/Writers Optimization • Single lock: safe, but limits concurrency • Only one thread at a time, but… • Safe to have simultaneous readers! • But only one writer at a time • Must guarantee mutual exclusion for writers
Readers/Writers: Example • Maximizes concurrency • Great! But how do we implement this? thread A Lock.acquire() Read data Lock.release() thread B Lock.acquire() Modify data Lock.release() thread C Lock.acquire() Read data Lock.release() thread D Lock.acquire() Read data Lock.release() thread E Lock.acquire() Read data Lock.release() thread F Lock.acquire() Modify data Lock.release()
Reader-Writer Locks • New synchronization operator:reader-writer lock • Multiple readers, just one writer • Can be built with standard synch primitives • E.g., semaphores
Readers/Writers Algorithm • As long as there are no writers • Let readers in • If no readers or writers • Let one writer in
Readers/Writers Algorithm • As long as there are no writers • Let readers in • If no readers or writers • Let one writer in reader
Readers/Writers Algorithm • As long as there are no writers • Let readers in • If no readers or writers • Let one writer in reader
Readers/Writers Algorithm • As long as there are no writers • Let readers in • If no readers or writers • Let one writer in reader reader
Readers/Writers Algorithm • As long as there are no writers • Let readers in • If no readers or writers • Let one writer in reader reader
Readers/Writers Algorithm • As long as there are no writers • Let readers in • If no readers or writers • Let one writer in reader reader reader
Readers/Writers Algorithm • As long as there are no writers • Let readers in • If no readers or writers • Let one writer in reader reader reader
Readers/Writers Algorithm • As long as there are no writers • Let readers in • If no readers or writers • Let one writer in reader reader reader writer
Readers/Writers Algorithm • As long as there are no writers • Let readers in • If no readers or writers • Let one writer in reader reader writer
Readers/Writers Algorithm • As long as there are no writers • Let readers in • If no readers or writers • Let one writer in reader reader writer writer
Readers/Writers Algorithm • As long as there are no writers • Let readers in • If no readers or writers • Let one writer in reader writer writer
Readers/Writers Algorithm • As long as there are no writers • Let readers in • If no readers or writers • Let one writer in writer writer
Readers/Writers Algorithm • As long as there are no writers • Let readers in • If no readers or writers • Let one writer in writer writer
Readers/Writers Algorithm • As long as there are no writers • Let readers in • If no readers or writers • Let one writer in writer writer reader
Readers/Writers Algorithm • As long as there are no writers • Let readers in • If no readers or writers • Let one writer in writer • What happens next? writer reader reader
Starvation Problem • Two possible policies: • No reader waits unless writer is already in • Waiting writer always gets served first • Both variants may lead to starvation • First: writers may starve • Second: readers may starve
Readers/Writers Algorithm • As long as there are no writers • Let readers in • If no readers or writers • Let one writer in writer variant 2 variant 1 writer reader • How to avoid starvation? reader
Implementing R/W Locks • Can implement with two semaphores • “Mutex”: protect number of readers • “Queue”: control scheduling of writers • Control access to a “database” • int getValue() • void setValue (int n)
Implementing R/W Locks class RWDatabase { private Database db; private int readers; private Semaphore mutex; private Semaphore writersSemaphore; RWInt() { readers = 0; mutex = new Semaphore (1); queue = new Semaphore (1); } int read() { … } void write (int n) { … } };
Implementing R/W Locks void RWDatabase::write (int v) { writersSemaphore.wait(); db.setValue(v); // Write the value writersSemaphore.signal(); }; Write value
Implementing R/W Locks int RWDatabase::read() { int v; mutex.wait(); readers++; if (readers == 1) { // I’m first reader writersSemaphore.wait(); } mutex.signal(); v = db.getValue(); mutex.wait(); readers--; if (readers == 0) { // I’m last reader writersSemaphore.signal(); } mutex.signal(); return v; }; Add a reader Read, remove reader • Who can starve?
Problems withSemaphores & Locks • Much better than load/store • Still many drawbacks • Serve two purposes • Mutual exclusion • Scheduling constraints • Effectively shared global variables • Access to semaphores may be anywhere • Not structured • Not tied to data they control access to
Monitors • Invented by C.A.R. “Tony” Hoare for Mesa • Also invented quicksort, “Hoare triples” {a > 16}a = sqrt(a);{ a > 4 } • monitor = Java class with: • All data private • All methods synchronized
Implementing Monitors in Java class QueueMonitor { private queue q; public void synchronized add (Object item) { q.add (item); } public Object synchronized remove() { if (q.notEmpty()) { Object o = q.remove(); return o; } else { // what should we do here? } };
Remove Options • Options for remove when queue empty: • Return special error value (e.g., NULL) • Throw an exception • Wait for something to appear in the queue • Wait = sleep() • But sleep inside synchronized… • Holds lock • Goes to sleep • Never wakes up!
Condition Variables • Queue of threads waiting in critical section • Thread must hold lock when performing operations: • wait(Lock l) • Atomically releases lock, goes to sleep • Reacquires lock when awakened • notify() • Wakes up one waiting thread, if any • notifyAll() • Wakes up all waiting threads
Implementing Monitors in Java class QueueMonitor { private queue q; public void synchronized add (Object item) { q.add (item); notify(); } public Object synchronized remove() { while (q.empty()) { wait(); } return q.remove(); } };
R/W Locks in Java class RWDatabase { private Database db; private int readers; private int writers; RWInt() { readers = 0; } public synchronized int read() { … } public synchronized void write (int n) { … } };
R/W Locks in Java public int RWDatabase::read() { preRead(); int v = db.getValue(); postRead(); return v; }; private void synchronized preRead() { while (writers > 0) wait(); readers++; } private void synchronized postRead() { readers--; if (readers == 0) notify(); }
R/W Locks in Java public synchronized void RWDatabase::write (int v) { preWrite(); db.setValue(v); postWrite(); } private void preWrite() { writers++; while (readers > 0) wait(); } private void postWrite() { writers--; notify(); }
Summary • Reader-Writer Locks • Permit concurrent reads • Implementable with semaphores • Monitors • Classes: tie data, methods with synchronization • Condition Variables • Release lock temporarily • Waiting inside critical sections
Next Time • Deadlock