Transcript lec14

Operating Systems
CMPSC 473
Mutual Exclusion
Lecture 14: October 14, 2010
Instructor: Bhuvan Urgaonkar
Mid-semester feedback
• On Angel, format similar to SRTEs
• Please submit by end of the week
• Based on feedback so far: will do a revision of
mutual exclusion related topics
Agenda
• Some classic synchronization problems using semaphores
• Last class
– Producer/Consumer problem
– Readers/Writers problem
• Solution was free of deadlocks
• Starvation problem
• Today
– Readers/Writers problem
• Consider more carefully the definition of starvation
– Dining Philosophers problem
Readers-Writers Problem
• A data set shared among a number of concurrent processes
– Readers – only read the data set; they do not perform any updates
– Writers – can both read and write
• Problem – allow multiple readers to read at the same time. Only one
writer may access the shared data at a given time
• Shared Data
–
–
–
–
Data set
Semaphore mutex initialized to 1
Semaphore wrt initialized to 1
Integer readcount initialized to 0
Readers-Writers Problem (Cont.)
• The structure of a writer process
do {
wait (wrt) ;
Allow only one
// writing is performed
writer at a time
to write
signal (wrt) ;
} while (TRUE);
mutex = 1
wrt = 1
readcount = 0
Readers-Writers Problem (Cont.)
• The structure of a reader process
do {
Proceed only if wait (mutex) ;
no writer is
readcount ++ ;
writing; disallowif (readcount == 1) wait (wrt) ;
writers once we signal (mutex) ;
proceed
// reading
Signal a writer wait (mutex) ;
only when there readcount - - ;
if (readcount == 0)
are no more
signal (wrt) ;
active readers
signal (mutex) ;
} while (TRUE);
mutex = 1
wrt = 1
readcount = 0
Readers/Writers
• Note that starvation is said to occur only when a process,
despite getting CPU, does not get to make use of it
– Only writers are starved, not readers
• Can we eliminate starvation for writers?
Dining-Philosophers Problem
• Shared data
– Bowl of rice (data set)
– Semaphore chopstick [5] initialized to 1
Dining-Philosophers
Problem (Cont.)
• The structure of Philosopher i:
do {
wait ( chopstick[i] );
wait ( chopStick[ (i + 1) % 5] );
// eat
signal ( chopstick[i] );
signal (chopstick[ (i + 1) % 5] );
// think
} while (TRUE);
Deadlock?
Starvation?
What happens
if all pick their
left chopsticks?
Dining-Philosophers
Problem (Cont.)
• Idea #1: Make the two wait operations occur together
as an atomic unit (and the two signal operations)
– Use another binary semaphore for this
– Any problems with this?
Dining-Philosophers
Problem (Cont.)
• Idea #2: Does it help if one of the neighbors picks
their left chopstick first and the other picks their right
chopstick first?
• What is the most # phils. that can eat simultaneously?
Bounded Buffer/
Producer Consumer
Producer
N=4
2 empty slots
Consumer
2 occupied slots
• Buffer has max capacity N
• Producer can only add if buffer has room (i.e., count < N)
• Consumer can only remove if buffer has item (i.e., count > 0)
Producer Consumer: Mutex Locks
mutex_lock m;
int count = 0;
Produce() {
while (count == N);
mutex_lock (m);
… ADD TO BUFFER, count++ …
}
mutex_unlock (m);
• Downside: Busy waiting
• Liveness guarantee depends
on how lock is implemented
– E.g.,
– Peterson’s => Mutex and
bounded wait
– Test&set => Only mutex
Consume() {
while (count ==0);
mutex_lock (m);
… REMOVE FROM BUFFER, count-- …
}
mutex_unlock (m);
Binary Semaphores == Mutex Locks
semaphore m = 1;
int count = 0;
Produce() {
while (count == N);
wait (m);
… ADD TO BUFFER, count++ …
}
signal (m);
Consume() {
while (count ==0);
wait (m);
… REMOVE FROM BUFFER, count-- …
}
signal (m);
Producer Consumer: Semaphores
semaphore sem = 1;
semaphore full = 0;
semaphore empty = N;
Produce() {
wait (empty);
wait (sem);
… ADD TO BUFFER, count++ …
signal (sem);
signal (full);
}
Consume() {
wait (full);
wait (sem);
… REMOVE FROM BUFFER,
signal (sem);
signal (empty);
}
• Use three semaphores
• Note important difference
from condition variables
– Signals are not lost
• sem protects critical sections
• full forces a consumer to wait
till there is at least one item in
buffer
• empty ensures at most N
items are produced between
empty buffer and execution of
count-- … a consumer
Producer Consumer: Semaphores
semaphore sem = 1; int count = 0;
Produce() {
if (count == N)
wait (sem);
… ADD TO BUFFER, count++ …
}
signal (sem);
• A non-working example
– Identify the race condition here
– That is, can a producer and
consumer be in their critical
sections simultaneously?
Consume() {
if (count == 0)
wait (sem);
… REMOVE FROM BUFFER, count-- …
}
signal (sem);
Producer Consumer: Semaphores
semaphore sem = 1; int count = 0;
mutex_lock m;
Produce() {
mutex_lock (m);
if (count == N) wait (sem);
… ADD TO BUFFER, count++ …
signal (sem);
mutex_unlock (m);
}
• A non-working example
• What happens if a consumer
acquires the lock before an
item is added to the buffer?
– Deadlock!
Consume() {
mutex_lock (m);
if (count == 0) wait (sem);
… REMOVE FROM BUFFER, count-- …
signal (sem);
mutex_unlock (m);
}