Presentation is loading. Please wait.

Presentation is loading. Please wait.

Operating Systems Semaphores II

Similar presentations


Presentation on theme: "Operating Systems Semaphores II"— Presentation transcript:

1 Operating Systems Semaphores II

2 Producer/Consumer Problem
Consumer must wait for producer to fill buffers, if none full (scheduling constraint) Producer must wait for consumer to empty buffers, if all full Only one thread can manipulate buffer queue at a time (mutual exclusion) Use a separate semaphore for each constraint

3 P() is a Generalization of Sleep()
int BUFFER_SIZE = 100; int count = 0;  void producer(void) { int item; while(TRUE) { produce_item(&item); if(count == BUFFER_SIZE) sleep (); enter_item(item); count++; if(count == 1) wakeup(consumer); }}  void consumer(void) { int item; if(count == 0) remove_item(&item); count--; if(count == BUFFER_SIZE - 1) wakeup(producer); consume_item(&item); }} P() is a Generalization of Sleep() Mutual Exclusion Scheduling Constraint 1 Scheduling Constraint 2 V() is a Generalization of Wakeup()

4 P() is a Generalization of Sleep()
int BUFFER_SIZE = 100; int count = 0;  void producer(void) { int item; while(TRUE) { produce_item(&item); if(count == BUFFER_SIZE) sleep (); enter_item(item); if(count == 1) wakeup(consumer); }}  void consumer(void) { int item; if(count == 0) remove_item(&item); if(count == BUFFER_SIZE - 1) wakeup(producer); consume_item(&item); }} P() is a Generalization of Sleep() Mutual Exclusion Sleep if buffer full Get Exclusive Access of Queue Leave Exclusive Access of Queue Wake up if first item in buffer Scheduling Constraint 1 Scheduling Constraint 2 Sleep if buffer empty V() is a Generalization of Wakeup() Get Exclusive Access of Queue Leave Exclusive Access of Queue Wake up if space in buffer

5 Get Exclusive Access of Queue
int BUFFER_SIZE = 100; int count = 0;  void producer(void) { int item; while(TRUE) { produce_item(&item); empty->P(); CountMutex->P(); enter_item(item); CountMutex->V(); full->V(); }}  void consumer(void) { int item; full->P(); remove_item(&item); empty->V(); consume_item(&item); }} Semaphore Empty(BUFFER_SIZE); Semaphore full(0); Semaphore CountMutex(1); Mutual Exclusion Sleep if buffer full Get Exclusive Access of Queue Leave Exclusive Access of Queue Wake up if first item in buffer Producer/Consumer Problem solved with Semaphores Scheduling Constraint 1 Scheduling Constraint 2 Sleep if buffer empty Get Exclusive Access of Queue Leave Exclusive Access of Queue Wake up if space in buffer

6 Semaphore API #include <semaphore.h> How to declare semaphore?
sem_t S; Initialization… sem_init(&S,0,1); Decrement ( P()) sem_wait(&S); Increment ( V() ) sem_post(&S); Max Value

7 Example - Ping Pong… Suppose we have two threads A and B
A and B are to repeatedly print out ping and pong, respectively We want to execute them in an alternating order An alternating execution would force A and B to print out in the order of ping pong ping pong ping pong Write the pseudocode of the thread A and B How can this be solved with and without semaphores

8 Example - Threads A Thread creates 5 Threads. Thread 1 is created first, Thread 2 is created second, Thread 3 is created third and so on. Assume FIFO to be the scheduling policy. Each thread prints the sequence number of its creation. Write the code that will print exactly the following: I am Thread 5, I was created at number 5 I am Thread 3, I was created at number 3 I am Thread 4, I was created at number 4 I am Thread 1, I was created at number 1 I am Thread 2, I was created at number 2

9 Example … A thread may delay its execution by calling a function
Void Delay(int second) The thread itself is blocked (no busy waiting by this thread) Wakesup roughly after second Hint I: A new thread is spawned whenever delay is called Hint II: Loops for delay?

10 What will happen if we swap
int BUFFER_SIZE = 100; int count = 0;  void producer(void) { int item; while(TRUE) { produce_item(&item); empty->P(); CountMutex->P(); enter_item(item); CountMutex->V(); full->V(); }}  void consumer(void) { int item; full->P(); remove_item(&item); empty->V(); consume_item(&item); }} Semaphore Empty(BUFFER_SIZE); Semaphore full(0); Semaphore CountMutex(1); What will happen if we swap empty->P(); CountMutex->P();

11 DEADLOCK Suppose the buffer is full Where is the producer???
int BUFFER_SIZE = 100; int count = 0;  void producer(void) { int item; while(TRUE) { produce_item(&item); CountMutex->P(); empty->P(); enter_item(item); CountMutex->V(); full->V(); }}  void consumer(void) { int item; full->P(); remove_item(&item); empty->V(); consume_item(&item); }} Semaphore Empty(BUFFER_SIZE); Semaphore full(0); Semaphore CountMutex(1); Suppose the buffer is full Where is the producer??? Where is the consumer??? DEADLOCK

12 Solution One has to be really careful while working with the Semaphores Problem with semaphores: Used for both mutex and scheduling constraints. This makes the code hard to read, and hard to get right. Monitor: A higher level synchronization primitive Separate these 2 concepts: use locks for mutual exclusion condition variables for scheduling constraints.

13 Monitor A Monitor consists of
A lock Zero or more condition variables For managing concurrent access to shared data Only one process can be active in the monitor at a time Acquire the lock on entry and Release the lock before returning. With condition variables, the module methods may wait and signal on multiple independent conditions.

14 Locks: A simple example
AddToQueue() { lock.Acquire(); // lock before using shared data put item on queue; // ok to access shared data lock.Release(); // unlock after done with shared data } RemoveFromQueue() { if something on queue // ok to access shared data remove it; return item; “Roughly Equivalent” to a semaphore with value 1 Restriction that the thread that “locks” must be the one that unlocks it.

15 A simple example How do we change RemoveFromQueue() to wait until something is on the queue? Logically, want to go to sleep inside of critical section But if hold lock when go to sleep? other threads won't be able to get in to add things to the queue And then wake up the sleeping thread

16 Condition Variables: Sleep inside critical section, by atomically releasing lock at same time we go to sleep Condition variable: A queue of threads Waiting for something inside a critical section.

17 Condition Variables: Support three operations
Wait() release lock, go to sleep, re-acquire lock Releasing lock and going to sleep is atomic Signal() wake up a waiter, if any Broadcast() wake up all waiters Rule: must hold lock when doing condition variable operations.

18 A simple example AddToQueue() {
lock.Acquire(); // lock before using shared // data put item on queue; // ok to access shared data condition.signal(); lock.Release(); // unlock after done with // shared data } RemoveFromQueue() { lock.Acquire(); while nothing on queue condition.wait(&lock);// release lock; go // to sleep; // re-acquire lock remove item from queue; lock.Release(); return item;}

19 How is a conditional variable different from Semaphore?
What if thread calls V() and no one is waiting? Increment – Wakeup is saved. What if thread later does calls P()? Decrement and continue – Wakeup is used. P + V are commutative Result is the same no matter what order they occur. What if thread signals and no one is waiting? Nothing Happens – No Wakeups are saved. What if thread later waits? Thread waits.

20 How is a conditional variable different from Semaphore?
Conditional Variables are not counters Just unblock a thread if one is blocked on the conditional variable No counter incremented/decremented Just like Sleep/Wakeup except that this is atomic That's why they must be accessed in a critical section Before waiting, must check the state variables.

21 Producer/Consumer Problem with Monitor
Constraints 1. Producers can produce if buffer not full Condition: okToProduce 2. Consumers can consume if buffer not empty Condition: okToConsume 3. Only one thread manipulates state variables at a time.

22 int empty = BUFFER_SIZE;  
void producer(void) { int item; while(TRUE) { produce_item(&item); mutex->lock(); if(empty < = 0) okToProduce->Wait(&mutex); enter_item(item); empty--; okToConsume->Signal(); mutex->unlock();}}  void consumer(void) { int item; if(empty >= BUFFER_SIZE) okToConsume->Wait(&mutex); remove_item(&item); empty++; okToProduce->Signal(); mutex->unlock(); consume_item(&item);}}


Download ppt "Operating Systems Semaphores II"

Similar presentations


Ads by Google