review: producer-consumer using semaphores #define n 100// number of slots in the buffer semaphore...

21
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 Dead Lock!

Post on 20-Dec-2015

232 views

Category:

Documents


2 download

TRANSCRIPT

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 }}

8

Barriers: Synchronizing A Group

A

B

C

D

Bar

rier

Time

A

B

C

D

Bar

rier

Time

A

B

C

D

Bar

rier

Time

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

Outline

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

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}