Database reader/writer problem CS 361 Concurrent programming Drexel University Fall 2004 Lecture 14 ©Bruce Char and Vera Zaychik. All rights reserved by the author. Permission is given to students enrolled in CS361 Fall 2004 to reproduce these notes for their own use. page 1 • The readers and writers problem: readers may read a database simultaneously as long as no writer writes • Only one writer at a time may write (if there are no active readers). • Attain: maximal parallelism (readers may read simultaneously if there is no writing), data integrity (only one writer at a time if no readers are reading). • Possible additional goal: avoid writer starvation (locked out of writing because readers are always coming along to read). page 2 Database reader/writer solution import Utilities.*; import Synchronization.*; class Database extends MyObject { private int numReaders = 0; private BinarySemaphore mutex = new BinarySemaphore(1); private BinarySemaphore ok = new BinarySemaphore(1); public Database() { super("Database"); } Reader code public void startRead(int i) { P(mutex); numReaders++; if (numReaders == 1) { System.out.println("age=" + age() + " reader " + i + " waiting to read, numReaders=" + numReaders); P(ok); } System.out.println(" age=" + age() + " reader " + i + " has begun reading, numReaders=" + numReaders); V(mutex); } public void endRead(int i) { P(mutex); numReaders--; System.out.println(" age=" + age() + " reader " + i + " finished reading, numReaders=" + numReaders); if (numReaders == 0) V(ok); V(mutex); } page 4 page 3 Writer code public void startWrite(int i) { P(ok); System.out.println(" age=" + age() + " WRITER " + i + " has begun Writing"); } public void endWrite(int i) { System.out.println(" age=" + age() + " WRITER " + i + " has finished Writing"); V(ok); } Notes on reader/writer solution – Only the first reader should lock the “ok” lock. The last reader should unlock it when it finishes its read. Then the – Writers can write. Starvation of writers might occur. } page 5 page 6 1 Preventing starvation of writers • “Serialization” – Use a queue for all (makes any reader wait who arrives after a writer). • “Platooning” – Use a queue for waiting threads, and have a separate “active group” of threads. – While readers in the active group are working, writers wait in the queue. – If a writer is waiting, any later reader must wait in the queue. – After a writer finishes, it sweeps all the waiting readers into the active group (even if they have arrived after the next writer). – Avoids starvation but increases parallelism. page 7 How do you do this? • Hint: try time stamping a reader’s or writer’s arrival to keep track of who should proceed or not. page 8 A problem to solve Baboons, cont. • Baboons crossing a canyon • A canyon cuts through the territory of a colony of baboons. the baboons use a rope stretching across the canyon to cross from one side to the other. the rope is strong enough to permit any number of baboons to cross in the same direction at the same time, but is too thin to allow baboons to cross in both directions at once. • So a baboon that wants to cross from west to east must wait until all westward moving baboons have finished and the rope is free, and vice versa. • If the rope is being used by westward-moving baboons, then other baboons may start to cross from east to west no matter how many eastwardmoving baboons are waiting. page 9 page 10 How to solve it • First, write your program without worrying about a series of eastward-moving baboons holding up the waiting westward-moving ones (i.e. don’t worry about starvation). • Then modify your program so that it is fair and there is no starvation. Use serialization or platooning to do this (or another method of your invention). page 11 Deadlock with semaphores – Deadlock can happen through a typo: – P(s); critical section; P(s); page 12 2 Another way to get into trouble Thread #1 P(S); … P(T); … V(T); … V(S); A: P(S) succeeds B:P(T) succeeds A: blocks on P(T) B: blocks on P(S). page 13 Thread #2 P(T); … P(S);..V(S); … V(T); How to avoid the trouble of interlocking semaphores • One way to avoid deadlock on semaphores is to assign a global order to all semaphores and require that all threads decrement (P operation) semaphores according to global order. “It is impossible for a set of threads to develop in which each thread is blocked waiting for a semaphore to be released (incremented) while holding another semaphore.” Why? • Suppose all n threads are blocked. They are using semaphores S1, S2, S3, … Sn. Look at these threads in the total ordering. Let the thread that’s last in the total ordering be Sk. Then someone else must have caused Sk’s value to become zero by doing a P(Sk) operation. But if that thread is blocked itself, it must be doing a P(Sl),where l is not k. But how can that be? It must have done a P(Sk) before the current P(Sl), and that violates the rule that you do P(Sk) after P(Sl). • Endpageof14proof. 3