Download presentation
Presentation is loading. Please wait.
1
Review: Producer-Consumer using Semaphores #define N 100// number of slots in the buffer Semaphore mutex = 1;// controls access to critical region Semaphore empty = N;// counts empty buffer slots Semaphore 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
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
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.
4
Producer-Consumer With Monitors Monitor 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); end End; Procedure consumer; Begin while true do begin item := ProducerConsumer.remove; consume_item(item) end End; Not a system call
5
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
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
7
Producer-Consumer With Message Passing #define N 100// number of slots in the buffer void 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 }
8
8 Barriers: Synchronizing A Group A B C D Barrier Time A B C D Barrier Time A B C D Barrier Time
9
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
10
10 Outline Processes Threads Inter-process communication (IPC) Classical IPC problems Scheduling
11
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 0 1 24 3 0 1 2 34
12
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
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
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.
15
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 eating int state[N];//array to keep track of everyone’s state semaphore 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}
16
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
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
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
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.
20
semaphore customers For synchronization semaphore barbers For synchronization semaphore mutex For mutual exclusion int waiting a copy of customers
21
semaphore customers = 0;//#customers waiting for service semaphore barbers = 0;//#barber waiting for customers semaphore mutex = 1;//for mutual exclusion int waiting = 0;//#customers are waiting (not being cut) void barber(void) { while (TRUE){ down(&customers); //go to sleep if #customers is 0 down(&mutex); //acquire access to waiting waiting=waiting-1;//decrement count of waiting customers up(&barbers);//one barber is ready to cut hair up(&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 necessary up(&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 }
Similar presentations
© 2024 SlidePlayer.com. Inc.
All rights reserved.