Review: Producer-Consumer using Semaphores #define N 100// number of slots in the buffer Semaphore...
-
date post
20-Dec-2015 -
Category
Documents
-
view
232 -
download
2
Transcript of Review: Producer-Consumer using Semaphores #define N 100// number of slots in the buffer Semaphore...
Review: Producer-Consumer using Semaphores
#define N 100 // number of slots in the bufferSemaphore mutex = 1; // controls access to critical regionSemaphore empty = N; // counts empty buffer slotsSemaphore full = 0; // counts full buffer slots
void producer(void){ int item; while (TRUE){ item = produce_item(); // generate something to put in buffer down(&mutex); // enter critical region down(&empty); // decrement empty count insert_item(item); // put new item in buffer up(&mutex); // leave critical region up(&full); // increment count of full slots }}
void consumer(void){ int item; while (TRUE){ down(&mutex); // enter critical region down(&full); // decrement full count item = remove_item(); // take item from buffer up(&mutex); // leave critical region up(&empty); // increment count of empty slots }}
Dead Lock!
2
Monitor Monitor: a collection of procedures, variables
and data structures that grouped together Processes can call procedures in a monitor, but
cannot access its internal variables (private!) Only one procedure can be active in a monitor at
any instant. (How to guarantee?) Provide an easy way to achieve mutual
exclusion Compiler takes charge of mutual exclusion, not
the programmer. But how about synchronization?(P-C
problem)
3
Condition Variables Two operations:
wait(cond): block the caller on cond. And allow another process previously prohibited from entering the monitor to enter now. (avoid deadlock)
signal(cond): wake up one process blocked on cond
Only appear as the final statement in a monitor procedure (why?)
Condition variables are not counters. To avoid lost-wakeup problem, the wait
must come before signal.
Producer-Consumer With MonitorsMonitor ProducerConsumer condition full, empty; integer count;
procedure insert(item: integer); begin if count = N then wait(full); insert_item(item); count := count + 1; if count = 1 then signal(empty) end;
function remove: integer; begin if count = 0 then wait(empty); remove = remove_item; count := count –1; if count = N – 1 then signal(full) end;
count :=0;End monitor;
Procedure producer;Begin while true do begin item := produce_item; ProducerConsumer.insert(item); endEnd;
Procedure consumer;Begin while true do begin item := ProducerConsumer.remove; consume_item(item) endEnd;
Not a system call
5
Sleep/Wakeup Vs. Monitor Why sleep/wake fails?
The wake-up call is sent before the sleep call.
With monitor, that cannot happen Only one process can be active in a
monitor Wait call is always before signal
Monitors in programming language Keyword synchronized in Java
6
Message Passing Two primitives (system calls)
Send(destination, &message) Receive(destination, &message)
Receiver blocks until receiving one message Acknowledgement of messages
Sender resends messages if timeout Buffered messages/rendezvous
Mail box: hold up to n messages Block senders if mail box is full
Rendezvous: block senders if receivers are not ready
Producer-Consumer With Message Passing
#define N 100 // number of slots in the buffervoid consumer(void){ int item, i; message m; for(i = 0; i < N; i++) send(producer, &m); // send N empties while (TRUE){ receive(producer, &m); item = extract_item(&m); // extract item from message send(producer, &m); // send back empty reply }}
void producer(void){ int item; message m; // message buffer while (TRUE){ item = produce_item(); receive(consumer, &m); // wait for an empty to arrive build_message(&m, item); // construct a message to send send(consumer, &m); // send item to consumer }}
9
Summary
Race conditions Critical regions Mutual exclusion
No two processes are in their critical regions at the same time
Synchronization Busy waiting, sleep and wakeup,
semaphore, mutex, monitor, message passing, barrier Please compare these primitives
11
Dining Philosophers Problem
Philosophers: loop of eating + thinking Pick up two forks, one at a time No predefined order in acquiring folks Philosopher process forks resources.
Goals: No deadlock No starvation Efficient
01
24
3
0 12
34
Naïve Solution#define N 5 // number of philosophers
Void philosopher(int j){ // j: philosopher number, from 0 to 4
while (TRUE){
think(); // philosopher is thinking
take_fork(j); // take left fork, blocked if fork unavailable
take_fork((j+1) % N); // take right fork; % is modulo operator
eat(); // yum-yum, spaghetti
put_fork(j); // put left fork back on the table
put_fork((j+1) % N); // put right fork back on the table
}}
What if all philosophers take left forks simultaneously? A deadlock!
13
Solutions with Starvation What if a philosopher put down left fork
if the right fork is not available? If all philosophers action simultaneously, the
program runs indefinitely without progress Starvation!
All the processes continue to run indefinitely but fail to make any progress.
Different from deadlock. What about waiting for a random time if
the right fork is not available? May work in practice, low failure probability Not absolutely safe!
14
Safe Solution May Not Be Good
Allow at most ONE philosopher eat at a time Definitely safe, no competition for forks Low efficiency, at least 3 forks are free
Better solution: a philosopher only eat if neither neighbor is eating Safe, no starvation, no deadlock. Maximal parallelism, at most 2
philosophers can eat at a time.
A Solution for Dining Philosopher Problem
#define N 5 //number of philosophers#define LEFT (i+N-1)%N //i’s left number#define RIGHT (i+1)%N //i’s right number#define THINKING 0 //philosopher is thinking#define HUNGRY 1 //philosopher is trying to get forks#define EATING 2 //philosopher is eatingint state[N]; //array to keep track of everyone’s statesemaphore mutex = 1; //mutual exclusion for critical regions
semaphore s[N] = 0; //one semaphore per philosopher
void philosopher(int i) //i: philosopher number, from 0 to N-1{ while (TRUE){ //repeat forever
think(); //philosopher is thinking take_forks(i); //acquire two forks or block
eat(); //eating put_forks(i); //put both forks back on table
}}
void take_forks(int i) //i: philosopher number, from 0 to N-1 { down(&mutex); //enter critical region state[i]=HUNGRY; //record the fact that philosopher i is hungry test(i); //try to acquire 2 forks up(&mutex); //exit critical region down(&s[i]); //block if forks were not acquired }
void put_forks(int i) //i: philosopher number, from 0 to N-1 { down(&mutex); //enter critical region state[i]=THINKING; //philosopher has finished eating test(LEFT); //see if left neighbor can now eat test(RIGHT); //see if right neighbor can eat up(&mutex); //leave critical region }
void test(int i) {
if ( state[i]==HUNGRY && state[LEFT] !=EATING && state[RIGHT]!=EATING){ state[i]=eating; up(&s[i]); }}
17
Saltshakers Solution Previous solution has starvation
problem. Why? Saltshakers solution: adding two tokens
to the table, perhaps saltshakers each philosopher first collects a saltshaker
before attempting to collect forks, then eats, and then puts the forks and saltshaker back. A philosopher has to wait if he/she fails to collect a saltshaker or a fork.
Deadlock free (why?), starvation free (assumption?), but less concurrency (how?)
18
The Readers and Writers Problem
Multiple readers/writers of a database No access to database when one is
writing First solution: A writer is admitted
only if there is no reader A writer may never get in!
Improved solution: A writer blocks readers after her Less concurrency
19
The Sleeping Barber Problem
One barber, one barber chair, and n chairs for waiting customers
Barber: working or sleeping (semaphore) Customer: (semaphore)
If the barber is sleeping, wake him up (lost signal)
If the barber is cutting other’s hair If there are empty chairs, wait Otherwise, leave
Program the barber and the customers without getting into race conditions.
semaphore customersFor synchronization
semaphore barbersFor synchronization
semaphore mutexFor mutual exclusion
int waitinga copy of customers
semaphore customers = 0; //#customers waiting for servicesemaphore barbers = 0; //#barber waiting for customerssemaphore mutex = 1; //for mutual exclusionint waiting = 0; //#customers are waiting (not being cut)void barber(void){ while (TRUE){
down(&customers); //go to sleep if #customers is 0down(&mutex); //acquire access to waitingwaiting=waiting-1; //decrement count of waiting
customersup(&barbers); //one barber is ready to cut hairup(&mutex); //release “waiting”cut_hair(); //cut hair
}}
void customer(void){ down(&mutex); //enter critical region if ( waiting < CHAIRS) { //if no free chair, leave waiting=waiting+1; //increment count of waiting customers
up(&customers); //wake up barber if necessaryup(&mutex); //release access to “waiting”down(&barbers); //go to sleep if barbers=0 get_haircut(); //be seated and serviced
}else { up(&mutex); } //shop is full, leave}