Review ProducerConsumer using Semaphores define N 100 Semaphore

  • Slides: 21
Download presentation
Review: Producer-Consumer using Semaphores #define N 100 Semaphore mutex = 1; Semaphore empty =

Review: Producer-Consumer using Semaphores #define N 100 Semaphore mutex = 1; Semaphore empty = N; Semaphore full = 0; // number of slots in the buffer // controls access to critical region // counts empty buffer slots // counts full buffer slots void producer(void){ int item; while (TRUE){ item = produce_item(); down(&mutex); down(&empty); insert_item(item); up(&mutex); up(&full); } } // generate something to put in buffer // enter critical region // decrement empty count // put new item in buffer // leave critical region // increment count of full slots void consumer(void){ int item; while (TRUE){ down(&mutex); down(&full); item = remove_item(); up(&mutex); up(&empty); } Dead Lock! // enter critical region // decrement full count // take item from buffer // leave critical region // increment count of empty slots } 1

Monitor n Monitor: a collection of procedures, variables and data structures that grouped together

Monitor n Monitor: a collection of procedures, variables and data structures that grouped together n n n Provide an easy way to achieve mutual exclusion n n 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? ) Compiler takes charge of mutual exclusion, not the programmer. But how about synchronization? (P-C problem) 2

Condition Variables n Two operations: n n wait(cond): block the caller on cond. And

Condition Variables n Two operations: n n 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 n n Only appear as the final statement in a monitor procedure (why? ) Condition variables are not counters. n To avoid lost-wakeup problem, the wait must come before signal. 3

Producer-Consumer With Monitors Monitor Producer. Consumer condition full, empty; integer count; Procedure producer; Begin

Producer-Consumer With Monitors Monitor Producer. Consumer condition full, empty; integer count; Procedure producer; Begin while true do begin procedure insert(item: integer); begin item : = produce_item; if count = N then wait(full); Producer. Consumer. insert(item); insert_item(item); end count : = count + 1; if count = 1 then signal(empty) End; end; Procedure consumer; function remove: integer; Begin Not a system begin while true do if count = 0 then wait(empty); call remove = remove_item; begin count : = count – 1; item : = Producer. Consumer. remove; if count = N – 1 then signal(full) consume_item(item) end; end count : =0; End monitor; 4

Sleep/Wakeup Vs. Monitor n Why sleep/wake fails? n n With monitor, that cannot happen

Sleep/Wakeup Vs. Monitor n Why sleep/wake fails? n n With monitor, that cannot happen n The wake-up call is sent before the sleep call. Only one process can be active in a monitor Wait call is always before signal Monitors in programming language n Keyword synchronized in Java 5

Message Passing n Two primitives (system calls) n n Send(destination, &message) Receive(destination, &message) n

Message Passing n Two primitives (system calls) n n Send(destination, &message) Receive(destination, &message) n n Acknowledgement of messages n n Receiver blocks until receiving one message Sender resends messages if timeout Buffered messages/rendezvous n Mail box: hold up to n messages n n Block senders if mail box is full Rendezvous: block senders if receivers are not ready 6

Producer-Consumer With Message Passing #define N 100 void consumer(void){ int item, i; message m;

Producer-Consumer With Message Passing #define N 100 void consumer(void){ int item, i; message m; for(i = 0; i < N; i++) send(producer, &m); while (TRUE){ receive(producer, &m); item = extract_item(&m); send(producer, &m); } } void producer(void){ int item; message m; while (TRUE){ item = produce_item(); receive(consumer, &m); build_message(&m, item); send(consumer, &m); } } // number of slots in the buffer // send N empties // extract item from message // send back empty reply // message buffer // wait for an empty to arrive // construct a message to send // send item to consumer 7

Barriers: Synchronizing A Group Barrier A B D C Time D Time A Barrier

Barriers: Synchronizing A Group Barrier A B D C Time D Time A Barrier C A Barrier B B C D Time 8

Summary n n n Race conditions Critical regions Mutual exclusion n No two processes

Summary n n n Race conditions Critical regions Mutual exclusion n No two processes are in their critical regions at the same time Synchronization Busy waiting, sleep and wakeup, semaphore, mutex, monitor, message passing, barrier n Please compare these primitives 9

Outline n n n Processes Threads Inter-process communication (IPC) Classical IPC problems Scheduling 10

Outline n n n Processes Threads Inter-process communication (IPC) Classical IPC problems Scheduling 10

Dining Philosophers Problem n Philosophers: loop of eating + thinking n n Pick up

Dining Philosophers Problem n Philosophers: loop of eating + thinking n n Pick up two forks, one at a time No predefined order in acquiring folks Philosopher process forks resources. 3 Goals: n n n No deadlock No starvation Efficient 4 4 3 2 0 1 11

Naïve Solution #define N 5 Void philosopher(int j){ while (TRUE){ think(); take_fork(j); take_fork((j+1) %

Naïve Solution #define N 5 Void philosopher(int j){ while (TRUE){ think(); take_fork(j); take_fork((j+1) % N); eat(); put_fork(j); put_fork((j+1) % N); } } // number of philosophers // j: philosopher number, from 0 to 4 // philosopher is thinking // take left fork, blocked if fork unavailable // take right fork; % is modulo operator // yum-yum, spaghetti // put left fork back on the table // put right fork back on the table What if all philosophers take left forks simultaneously? A deadlock! 12

Solutions with Starvation n What if a philosopher put down left fork if the

Solutions with Starvation n What if a philosopher put down left fork if the right fork is not available? n n If all philosophers action simultaneously, the program runs indefinitely without progress Starvation! n n n 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? n n May work in practice, low failure probability Not absolutely safe! 13

Safe Solution May Not Be Good n Allow at most ONE philosopher eat at

Safe Solution May Not Be Good n Allow at most ONE philosopher eat at a time n n n Definitely safe, no competition forks Low efficiency, at least 3 forks are free Better solution: a philosopher only eat if neither neighbor is eating n n Safe, no starvation, no deadlock. Maximal parallelism, at most 2 philosophers can eat at a time. 14

A Solution for Dining Philosopher Problem #define N 5 #define LEFT (i+N-1)%N #define RIGHT

A Solution for Dining Philosopher Problem #define N 5 #define LEFT (i+N-1)%N #define RIGHT (i+1)%N #define THINKING 0 #define HUNGRY 1 #define EATING 2 int state[N]; semaphore mutex = 1; semaphore s[N] = 0; //number of philosophers //i’s left number //i’s right number //philosopher is thinking //philosopher is trying to get forks //philosopher is eating //array to keep track of everyone’s state //mutual exclusion for critical regions //one semaphore per philosopher void philosopher(int i) { while (TRUE){ think(); take_forks(i); eat(); put_forks(i); //i: philosopher number, from 0 to N-1 } //repeat forever //philosopher is thinking //acquire two forks or block //eating //put both forks back on table } 15

void take_forks(int i) { down(&mutex); state[i]=HUNGRY; test(i); up(&mutex); down(&s[i]); } //i: philosopher number, from

void take_forks(int i) { down(&mutex); state[i]=HUNGRY; test(i); up(&mutex); down(&s[i]); } //i: philosopher number, from 0 to N-1 void put_forks(int i) { down(&mutex); state[i]=THINKING; test(LEFT); test(RIGHT); up(&mutex); } //i: philosopher number, from 0 to N-1 //enter critical region //record the fact that philosopher i is hungry //try to acquire 2 forks //exit critical region //block if forks were not acquired //enter critical region //philosopher has finished eating //see if left neighbor can now eat //see if right neighbor can eat //leave critical region void test(int i) { } if ( state[i]==HUNGRY && state[LEFT] !=EATING && state[RIGHT]!=EATING){ state[i]=eating; up(&s[i]); } 16

Saltshakers Solution n n Previous solution has starvation problem. Why? Saltshakers solution: adding two

Saltshakers Solution n n Previous solution has starvation problem. Why? Saltshakers solution: adding two tokens to the table, perhaps saltshakers n n 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? ) 17

The Readers and Writers Problem n Multiple readers/writers of a database n n First

The Readers and Writers Problem n Multiple readers/writers of a database n n First solution: A writer is admitted only if there is no reader n n No access to database when one is writing A writer may never get in! Improved solution: A writer blocks readers after her n Less concurrency 18

The Sleeping Barber Problem n n n One barber, one barber chair, and n

The Sleeping Barber Problem n n n One barber, one barber chair, and n chairs for waiting customers Barber: working or sleeping (semaphore) Customer: (semaphore) n n If the barber is sleeping, wake him up (lost signal) If the barber is cutting other’s hair n n n If there are empty chairs, wait Otherwise, leave Program the barber and the customers without getting into race conditions. 19

semaphore mutex For mutual exclusion int waiting a copy of customers semaphore customers For

semaphore mutex For mutual exclusion int waiting a copy of customers semaphore customers For synchronization semaphore barbers For synchronization 20

semaphore customers = 0; semaphore barbers = 0; semaphore mutex = 1; int waiting

semaphore customers = 0; semaphore barbers = 0; semaphore mutex = 1; int waiting = 0; void barber(void) { while (TRUE){ down(&customers); down(&mutex); waiting=waiting-1; up(&barbers); up(&mutex); cut_hair(); } } void customer(void) { down(&mutex); if ( waiting < CHAIRS) { waiting=waiting+1; customers up(&customers); up(&mutex); down(&barbers); get_haircut(); }else { up(&mutex); } } //#customers waiting for service //#barber waiting for customers //for mutual exclusion //#customers are waiting (not being cut) //go to sleep if #customers is 0 //acquire access to waiting //decrement count of waiting customers //one barber is ready to cut hair //release “waiting” //cut hair //enter critical region //if no free chair, leave //increment count of waiting //wake up barber if necessary //release access to “waiting” //go to sleep if barbers=0 //be seated and serviced //shop is full, leave 21