Synchronisation Examples Last time: Producer-Consumer using semaphores Today: some more examples Bounded Buffer Readers and Writers Dining Philosophers Sleeping Barber 159.302
What is the bounded buffer problem? This is just another name for the Producer-Consumer problem with a buffer. The solution uses two semaphores thingsinbuffer – initialised to zero spaceinbuffer – initialised to the buffer size The consumer waits on thingsinbuffer and signals spaceinbuffer after it has consumed. The producer waits on spaceinbuffer and signals thingsinbuffer after it has produced. 159.302
What is the Readers and Writers problem? Imagine a large database. Many processes are accessing the database Some only read (readers) and some read and write (writers). A Race conditions may exist where more than one writer is active or a writer and a reader is active. Any number of processes can read at the same time, but if a writer is writing then no other process must be able to access the data. 159.302
Solution to Readers and Writers Shared data semaphore mutex,norw; int readcount=0; mutex=create(1); norw=create(1); Writer process wait(norw); ... writing is performed ... signal(norw); Reader process wait(mutex); readcount = readcount + 1; if (readcount == 1) // first wait(norw); // one signal(mutex); ... reading is performed readcount = readcount - 1; if (readcount == 0) // first signal(norw); // one 159.302
Readers Writers Example 3 Processes At t=10 p1 read for 30ms At t=20 p2 read for 30ms At t=30 p3 write for 40ms At t=70 p1 read for 10ms At t=80 p2 read for 10ms 159.302
Readers Writers Example 1 -1 1 mutex 1 -1 -1 1 norw 1 2 1 1 2 readcount W P3 R R P2 R R P1 159.302
What is the dining philosophers problem? A Problem posed by Dijkstra in 1965. 5 people (philosophers) around a table each need 2 forks to eat. The philosophers alternately eat and think. 159.302
A Possible solution void philosopher(int no) { while(1) { ...think.... take_fork(no); /* get the left fork */ take_fork((no+1) % N); /* get the right fork */ ....eat..... put_fork(no); /* put left fork down */ put_fork((no+1) % N); /* put down right fork */ } "take_fork" waits until the specified fork is available and then grabs it. Unfortunately this solution will not work... what happens if all the philosophers grab their left fork at the same time. 159.302
A Better Solution Shared data Code int p[N]; /* status of the philosophers */ semaphore s[N]=0; /* semaphore for each philosopher */ semaphore mutex=1; /* semaphore for mutual exclusion */ Code #define LEFT(n) (n+N-1)%N /* Macros to give left */ #define RIGHT(n) (n+1)%N /* and right around the table */ void philosopher(int no) { while(1) { ...think.... take_forks(no); /* get the forks */ ....eat..... put_forks(no); /* put forks down */ } return NULL; 159.302
A Better Solution void test(int no) { /* can philosopher 'no' eat */ if ((p[no] == HUNGRY) && (p[LEFT(no)] != EATING) && (p[RIGHT(no)] != EATING) ) { p[no]=EATING; signal(s[no]); /* if so then eat */ } void take_forks(int no) { /* get both forks */ wait(mutex); /* only one at a time here please */ p[no]=HUNGRY; /* I'm Hungry */ test(no); /* can I eat? */ signal(mutex); wait(s[no]); /* wait until I can */ void put_forks(int no) { /* put the forks down */ wait(mutex); /* only one at a time here */ p[no]=THINKING; /* let me think */ test(LEFT(no)); /* see if my neighbours can now eat */ test(RIGHT(no)); 159.302
Philosopher Practice Think for a while Wait until mutex available and grab it. Look at people to your left and right If either of them is eating put down mutex and go to sleep otherwise put down mutex Eat for a while Wait until mutex available and grab it, meanwhile keep eating. Stop eating Look at person on your left If they are asleep wake them up if the person to their left is not eating. Look at person on your right If they are asleep wake them up if the person to their right is not eating. Repeat forever. 159.302
Fin 159.302