Each process has common variables, writing files,…
When one process in critical section, no other may be in its critical section
Requirements:
Mutual exclusion: if process Pi is executing in its CSi then Pj cannot execute CSj
Progress: if no process Pi is executing in CSi, then only those processes Pj that are not executing in {REMAINj} can be considered to enter {CSj} next and this selection cannot be postponed indefinitely.
Bounded waiting: Once a process Pi has made a request to enter CSi and before that request is granted, the number of times that PJ accessing CSj should be bounded
Solution: Each process must “ask permission” to enter entry of critical section, may follow critical section with exit section, then remainder section
with general structure:
Entry section
Critical section
Exit section
Remain section
Peterson’s solution:
Idea: if we have 2 processes, use 2 variables to control the access on critical sections
int turn: indicates whose turn is it to enter critical section (turn = i so i can enter)
boolean flag[2]: list of 2 booleans denoting candidate process is ready to enter (flag[i]=true means process i is waiting to enter)
ex: for process i
while (true) { flag[i] = true; turn = j; while (flag[j] && turn == j); // wait if its j's turn and j is in critical section /* critical section */ flag[i] = false // i is no longer candidate /* remainder section */}
Problem: only 2 processes running at the same time
Empty: count number of slots that are currently empty, initial = n
Full: count number of non-empty slot, intial = 0
* note that empty + full != n as one slot might being written to
Producer:
do { wait(empty) // wait until empty > 0 then empty -- wait(mutex) // acquire lock /* add data to buffer*/ signal(mutex) // release lock signal(full) // full++} while (TRUE)
Consumer
do { wait(full) // wait full > 0 wait(mutex) /* remove data */ signal(mutex) signal(empty)} while (TRUE)
Read-writer synchronization problem:
A database with many writers and many readers
2 readers at same time is ok
1 writer and 1 (reader or writer) is not ok
1 writer and 1 reader is not ok because: reader might read half old/half new data
→ When writer is writing, writer have exclusive access to the shared data
Solution: 2 semaphores and an integer
mutex: a Mutex Lock to lock on readcount, (init to 1)
readcount: an integer to keep track of how many processes reading the database (init to 0)
Writer:
do { wait(wrt); // wait for /* writing */ signal(wrt); // done writing} while (TRUE);
Reader:
do { wait(mutex); // wait and lock lock for readcount var readcount++; if (readcount == 1){ // if there is no other reader, if there was another reader means no writer writing cuz that would have waited for writer to be done wait(wrt); // wait for writer done writing } signal(mutex); // done modifying readcount /* reading */ wait(mutex) // wait and lock for readcount readcount--; if (readcount ==0){ // if there is no read other than this, let writers write signal(wrt); } signal(mutex); // done modifying readcount} while (TRUE)
Dining-philosophers problem
Five philosophers seated around a circular table, each with a plate of spaghetti.
To eat, a philosopher needs two forks: the one to their left and the one to their right.
If a philosopher picks up both forks, they can eat, but they can only pick up 1 at a time.
After eating, they put down both forks and think (wait)
monitor DiningPhilosophers { enum (THINKING; HUNGRY, EATING) state [5]; condition self [5]; void pickup (int i) { state [i] = HUNGRY; test (i) ; if (state[i] != EATING) self[i].wait(); } void putdown (int i) { state [i] = THINKING; // test left and right neighbors test ((i + 4) % 5); test ((i + 1) % 5); } void test (int i) { // if i am hungry and left and right folk are free if ((state[(i + 4) % 5] != EATING) && (state [i] == HUNGRY) && (state [(i + 1) % 5] != EATING) ) { state[i] = EATING ; self [i].signal () ; } } initialization_code () { for (int i = 0; i < 5; i++) state [i] = THINKING; } }