Operating Systems Synchronization part 3 Monitors classical sync

  • Slides: 27
Download presentation
Operating Systems Synchronization, part 3 Monitors, classical sync. problems 1

Operating Systems Synchronization, part 3 Monitors, classical sync. problems 1

Monitor • Monitor – a synchronization primitive • A monitor is a collection of

Monitor • Monitor – a synchronization primitive • A monitor is a collection of procedures, variables and data structures, grouped together • Mutual Exclusion – only one process can be active within a monitor at any given time • Usually a programming language construct! The compiler of the language will know that monitors procedures are different than other procedures, and will treat them differently. That means that the compiler is in charge of the mutual exclusion implementation 2

Condition variables • A way for processes to block when they can’t continue •

Condition variables • A way for processes to block when they can’t continue • Despite its name, it is used to indicate an event and not as a regular valued variable. A CV is not a counter! • Two operations: wait, signal Wait: causes the process to block, and allows entry of Wait other threads to the monitor Signal: Signal More than just one alternative: 1. Hoare type monitors: The signaler yields the monitor to the Hoare released thread. Signal will be the last operation within the monitor, which wakes up waiting processes (waiting on the same variable). This is not true for Java 2. Mesa type monitors: The signaling process is allowed to Mesa continue 3

The Sleeping Barber Write a solution to the sleeping barber problem using monitors and

The Sleeping Barber Write a solution to the sleeping barber problem using monitors and condition variables The sleeping barber: 1. 2. 3. 4. The barber cuts peoples hair in his shop, which has 2 doors – entrance and exit. When people are in his shop, he gives them a hair cut, one at a time. When none are in his shop, he sleeps on his chair. When a customer arrives and finds the barber sleeping, he awakens him and sits in the barber’s chair to receive his haircut. After the cut is done, the barber sees the customer out through the exit door. If the barber is busy when a customer arrives, the customer waits in one of the chairs in the shop. If all are occupied, he goes away. After serving a customer the barber looks to see if any are waiting and if so proceeds to serve one of them. Otherwise, he sleeps again in his chair. 4

The Sleeping Barber barbershop: monitor waiting : integer : = 0; % customers waiting

The Sleeping Barber barbershop: monitor waiting : integer : = 0; % customers waiting for haircut customers : condition; % used by barber, wait for a customer barber : condition; % used by customer, wait for barber procedure seek-customer( ) % called by the barber begin if waiting==0 then WAIT (customers); % sleeps if no customers waiting = waiting-1; % one less customer waiting cut-hair(); SIGNAL (barber); % free a waiting customer end seek-customer; 5

The Sleeping Barber procedure get-haircut( ) % called by a customer begin % is

The Sleeping Barber procedure get-haircut( ) % called by a customer begin % is there a free chair to sit and wait? % if no free chairs just go away if waiting < chairs then { waiting = waiting+1; SIGNAL (customers) WAIT (barber); } end get-haircut; end barbershop; % one more customer waiting % if the barber is asleep % wait for turn with the barber % End of monitor 6

Producer Consumers with Monitor Producer. Consumer 1. condition full, empty 2. integer count initially

Producer Consumers with Monitor Producer. Consumer 1. condition full, empty 2. integer count initially 0 3. procedure insert(item: integer) 4. begin 5. if count=N then wait(full) wait 6. insert_item(item) 7. count=count+1 8. signal(empty) signal 9. end 10. procedure remove: integer 11. begin 12. if count=0 then wait(empty) wait 13. remove=remove_item() 14. count=count-1 15. signal(full) signal 16. end Monitor 7

Producer Consumers with Monitor Producer. Consumer 1. condition full, empty 2. integer count initially

Producer Consumers with Monitor Producer. Consumer 1. condition full, empty 2. integer count initially 0 3. procedure insert(item: integer) 4. begin 5. if count=N then wait(full) wait 6. insert_item(item) 7. count=count+1 8. signal(empty) signal 9. end 10. procedure remove: integer 11. begin 12. if count=0 then wait(empty) wait 13. remove=remove_item() 14. count=count-1 15. signal(full) signal 16. end Monitor Will it work with Mesa type monitor? What about Hoare? 8

Java and monitors – Exercise Write a code snippet in Java which will enforce

Java and monitors – Exercise Write a code snippet in Java which will enforce a FIFO waking order (i. e. , create a class in Java that will allow a programmer fair synchronization) 11

Spurious wakeups • On some threading API’s (e. g. , for linux and windows)

Spurious wakeups • On some threading API’s (e. g. , for linux and windows) monitors and conditional variables are vulnerable to spurious wakeups. • Spurious wakeup describes a complication in the use of condition variables in which a thread might be awoken from its waiting state even though no thread signaled the condition variable. • Since Java uses the native threads implementation (native for the OS which is running the JVM) one must handle spurious wakeups. For correctness it is necessary, then, to verify that the condition is indeed true after the thread has finished waiting and continue waiting otherwise. 12

Java and monitors – Solution class Safe. Monitor { boolean released = false; }

Java and monitors – Solution class Safe. Monitor { boolean released = false; } // this flag avoids race!!! synchronized void await() throws Interrupted. Exception { while (! released) { wait(); } } synchronized void signal(){ if (! released){ released = true; notify(); } } 13

Java and monitors – Solution class Critical. Section { private List<Safe. Monitor> waiting; private

Java and monitors – Solution class Critical. Section { private List<Safe. Monitor> waiting; private boolean busy; public Critical. Section() { waiting = new Linked. List<>(); busy = false; } public void enter() { Safe. Monitor my. Lock = null; synchronized (this) { if (! busy) { busy = true; } else { my. Lock = new Safe. Monitor(); waiting. add(my. Lock); } } if (my. Lock != null) my. Lock. await(); } public synchronized void leave() { if (!waiting. is. Empty()) { waiting. remove(). signal(); } else { busy = false; } } } 14

Java and monitors – Solution class Critical. Section { private List<Safe. Monitor> waiting; private

Java and monitors – Solution class Critical. Section { private List<Safe. Monitor> waiting; private boolean busy; public synchronized void leave() { if (!waiting. is. Empty()) { waiting. remove(). signal(); } else { busy = false; } } } public Critical. Section() { waiting = new Linked. List<>(); busy = false; } public void enter() { Safe. Monitor my. Lock = null; synchronized (this) { if (! busy) { busy = true; } else { my. Lock = new Safe. Monitor(); waiting. add(my. Lock); Does this code guarantee a FIFO waking order } which is equivalent to the order in which } threads reached the critical section entrance? if (my. Lock != null) my. Lock. await(); What happens when multiple } threads attempt to enter at the same time? 15

The one-way tunnel problem • One-way tunnel • Allows any number of processes in

The one-way tunnel problem • One-way tunnel • Allows any number of processes in the same direction • If there is traffic in the opposite direction – have to wait • A special case of readers/writers 16

The one way tunnel (exam 2004) The one way tunnel solution: int Semaphore count[2];

The one way tunnel (exam 2004) The one way tunnel solution: int Semaphore count[2]; busy=1, mutex=1; waiting[2]={1, 1}; void arrive(int direction){ down(&waiting[direction]); down(&mutex) count[direction]+=1; if (count[direction]==1){ up(&mutex) down(&busy); } else up(&mutex) up(&waiting[direction]); } void leave(int direction){ down(&mutex); count[direction]-=1; if (count[direction]==0){ up(&busy); } up(&mutex); }

The one way tunnel (exam 2004) Add changes to the one way tunnel solution

The one way tunnel (exam 2004) Add changes to the one way tunnel solution so that there will be no starvation. If vehicles are present on both “ 0” and “ 1” they will take alternate turns in entering the tunnel. When there are vehicles coming from only one direction, they can pass through with no limitations. Notes: • you may only use integers and binary semaphores (can assume fairness).

The one way tunnel (exam 2004) The one way tunnel solution: int Semaphore count[2];

The one way tunnel (exam 2004) The one way tunnel solution: int Semaphore count[2]; busy=1, mutex=1, new_mutex=1; waiting[2]={1, 1}; void arrive(int direction){ down(&waiting[direction]); down(&new_mutex); down(&mutex); count[direction]+=1; if (count[direction]==1) { down(&mutex); down(&busy); } else up(&mutex) up(&new_mutex); up(&waiting[direction]); } void leave(int direction){ down(&mutex); count[direction]-=1; if (count[direction]==0){ up(&busy); } up(&mutex); }

One way, convoy (midterm 2008) In the following question you must implement a solution

One way, convoy (midterm 2008) In the following question you must implement a solution to the convoy problem using only semaphores (and regular variables). In this problem, each thread represent a vehicle. The vehicles must go through a one way tunnel, but unlike the tunnel problem, here vehicles may only cross the tunnel in groups of exactly 5 (all in the same direction). A group of another 5 vehicles (from the same or opposite direction) may cross the tunnel again, only after the previous group of 5 vehicles comes out of it. The general code structure is as follows: q Variable Declaration q Prepare. To. Cross(int direction) q CROSS q Done. With. Crossing(int direction)

One way, convoy (midterm 2008) Implement Prepare. To. Cross() and Done. With. Crossing(). For

One way, convoy (midterm 2008) Implement Prepare. To. Cross() and Done. With. Crossing(). For your implementation you may only use semaphores (counting or binary) and regular variables. No busy-waiting is allowed. We say a thread is passing the tunnel if it completed its call to tunnel Prepare. To. Cross and haven’t called Done. With. Crossing or if it is still in Prepare. To. Cross but is no longer waiting on a semaphore, and when it will receive CPU time it may complete the procedure without waiting. Your implementation must satisfy the following conditions: 1. 2. 3. Mutual Exclusion – threads from different direction may never be in the tunnel at the same time. Threads may only cross in groups of 5. When the first is leaving Prepare. To. Cross, there are exactly 4 others which are passing the tunnel as well. Progress – Whenever there are 5 (or more) threads from the same direction waiting to cross the tunnel, then eventually, 5 will.

One way, convoy (midterm 2008) We will use the following: Counting Semaphore waiting. To.

One way, convoy (midterm 2008) We will use the following: Counting Semaphore waiting. To. Cross[]={5, 5} Counting Semaphore barrier[]={0, 0} Counting Binary Semaphore busy=1 Binary Semaphore mutex=1 Binary int waiting. Count[]={0, 0} int passed=0

One way, convoy (midterm 2008) Prepare. To. Cross(int i){ down(&waiting. To. Cross[i]); down(&mutex); waiting.

One way, convoy (midterm 2008) Prepare. To. Cross(int i){ down(&waiting. To. Cross[i]); down(&mutex); waiting. Count[i]++; If (waiting. Count[i]<5){ up(&mutex); down(&barrier[i]); } else { waiting. Count[i]=0; up(&mutex); down(&busy); for (int k=0; k<4; k++) up(&barrier[i]); } up(&waiting. To. Cross[i]); } Done. With. Crossing(int i){ down(&mutex); passed++; if (passed==5){ passed=0; up(&busy); } up(&mutex); }

Message passing • Used on distributed systems (when there is no shared memory). •

Message passing • Used on distributed systems (when there is no shared memory). • Uses send(), and receive() system calls. • Introduces a new set of problems, such as acknowledgments, sequencing, addressing, authentication, etc’… 24

Reader/Writer problem with MP Write a solution to the reader/writer problem using Message Passing.

Reader/Writer problem with MP Write a solution to the reader/writer problem using Message Passing. Assume the following: 1. 2. 3. 4. Three groups of processes: readers, writer, manager. Multiple readers may access the DB simultaneously. A writer needs exclusive access to the DB. Readers have preference. 25

Reader/Writer problem with MP Reader: while (true){ SEND (manager, start_read); RECEIVE (manager, msg); %

Reader/Writer problem with MP Reader: while (true){ SEND (manager, start_read); RECEIVE (manager, msg); % wait for confirmation read_db(); SEND (manager, end_read); use_data(); } Writer: while (true){ generate_data(); SEND (manager, start_write); RECEIVE (manager, msg); % wait for confirmation write_to_db(); SEND (manager, end_write); } 26

Reader/Writer problem with MP Manager: int readers_count=0; % number of readers accessing DB boolean

Reader/Writer problem with MP Manager: int readers_count=0; % number of readers accessing DB boolean writing=false; % writing flag Message msg; Queue read. Q, write. Q; % Queues for waiting readers and writers Process. ID src; % pid while (true){ src = RECEIVE(msg); switch msg. type{ case (start_read): if (not writing){ send(src, ok); readers_count++; } else read. Q. add(src); 27

Reader/Writer problem with MP case (end_read): readers_count--; if (readers_count==0 && not write. Q. empty){

Reader/Writer problem with MP case (end_read): readers_count--; if (readers_count==0 && not write. Q. empty){ src=write. Q. remove; SEND (src, ok); writing = true; } case (start_write): if (readers_count==0 && not writing){ SEND (src, ok); writing = true; } else write. Q. add(src); 28

Reader/Writer problem with MP case (end_write): writing = false; if (read. Q. empty &&

Reader/Writer problem with MP case (end_write): writing = false; if (read. Q. empty && not write. Q. empty){ src = write. Q. remove; SEND(src, ok); writing = true; } else { while (not read. Q. empty){ src = read. Q. remove; send(src, ok); readers_count++; } } } % switch } % while 29