Semaphores: S S S0 + #V - #P
Semaphores: S S S0 + #V - #P
Semaphore Invariants
The following invariants are true for semaphores.
S≥0
S = S0 + #V - #P
page 28
Mutual Exclusion
sem mutex := 1
const N := 20
process p(i := 1 to N)
do true ->
Non_critical_Section
P(mutex)
Critical_Section
V(mutex)
od
end
QED
page 29
Theorem The program cannot deadlock.
#CS + mutex = 1 ⇒ 0 + 0 = 1
which is impossible.
Types of Semaphores
What we defined earlier is a general semaphore. A
binary semaphore is a semaphore that can only take the
values 0 and 1.
page 30
Theorem With busy-wait semaphores, starvation is
possible.
page 31
required to only wake one of them, so it could always
ignore one and leave that process starved.
#elements ≥ 0
page 32
var buffer [?]:int
var in_pointer:int := 0, out_pointer:int := 0
sem elements := 0
process producer
do true ->
buffer [in_pointer] := produce ()
in_pointer := in_pointer + 1
V(elements)
od
end
process consumer
var i:int
do true ->
P (elements)
i := buffer [out_pointer]
out_pointer := out_pointer + 1
consume (i)
end
page 33
const N := 100
var buffer [N]:int
var in_pointer:int := 0, out_pointer:int := 0
sem elements := 0
sem spaces := N
process producer
var i:int
do true ->
i := produce ()
P (spaces)
buffer [in_pointer] := i
in_pointer := (in_pointer + 1) mod N
V (elements)
od
end
process consumer
var i:int
do true ->
P (elements)
i := buffer [out_pointer]
out_pointer := (out_pointer + 1) mod N
V (spaces)
consume (i)
end
page 34
The Dining Philosophers Problem
The Problem
An institution hires five philosophers to solve a very
difficult problem. Each philosopher only engages in two
activities - thinking and eating. Meals are taken in the
diningroom which has a table set with five plates and
five forks. In the centre of the table is a bowl of spaghetti
that is endlessly replenished. The philosophers, not being
the most dextrous of individuals, requires two forks to
eat; and may only pick up the forks immediately to his
left and right.
page 35
c) No deadlock.
d) No individual starvation.
page 36
This is called a symmetric solution since each task is
identical. Symmetric solutions have many advantages,
particularly when it comes to load-balancing.
A Symmetric Solution
sem Room := 4
sem fork [5] := ([5] 1)
page 37
process philosopher (i := 1 to 5)
do true ->
Think ( )
P (Room)
P(fork [i])
P(fork [(i+1) mod 5]
Eat ( )
V(fork [i])
V(fork [(i+1) mod 5]
V (Room)
od
end
Room semaphore
page 38
fork [i]
Readers-Writers Problem
The Problem
Two kinds of processes, readers and writers, share a
database. Readers execute transactions that examine the
database, writers execute transactions that examine and
update the database. Given that the database is initially
consistent, then to ensure that the database remains
consistent, a writer process must have exclusive access to
page 39
the database. Any number of readers may concurrently
examine the database.
page 40
process writer (i:= 1 to N)
do true ->
P (rw)
Update_Database ( )
V (rw)
od
end
page 41
const M:int := 20, N:int := 5
var nr:int :=0, nw:int := 0
var sr:int := 0, sw:int := 0 # count of suspended
# readers and writers
sem e := 1, r := 0, w := 0 # 0 ≤ (e+r+w) ≤ 1
Read_Database ( )
P (e)
nr := nr - 1
if nr = 0 and sw > 0 -> sw := sw - 1; V (w)
[] nr >0 or sw = 0 -> V (e)
fi
od
end
page 42
process writer (i:= 1 to N)
do true ->
P (e)
if nr > 0 or nw > 0 ->
sw := sw + 1; V (e); P (w)
fi
nw := nw + 1
V (e)
Update_Database ( )
P (e)
nw := nw - 1
if sr > 0 -> sr := sr -1; V (r)
[] sw > 0 -> sw := sw - 1; V (w)
[] sr = 0 and sw = 0 -> V(e)
fi
od
end
page 43
Monitors
The main disadvantage with semaphores is that they
are a low level programming construct. In a large project,
with many programmers, if one programmer forgets to do
V( ) operation on a semaphore after a critical section,
then the whole system can deadlock.
Condition Variables
Synchronisation is achieved by using condition
variables. These are data structures that have 3
operations defined for them.
page 44
wait (C) The process that called the monitor
containing this operation is
suspended in a FIFO queue
associated with C. Mutual exclusion
on the monitor is released.
page 45
Readers/Writers Problem
_monitor (RW_controller)
op request_read ( ), release_read ( )
op request_write ( ), release_write ( )
_body (RW_controller)
var nr:int := 0, nw:int := 0
_condvar (ok_to_read)
_condvar (ok_to_write)
_proc (request_read ( ))
do nw > 0 -> _wait (ok_to_read) od
nr := nr + 1
_proc_end
_proc (release_read ( ))
nr := nr - 1
if nr = 0 -> _signal (ok_to_write) fi
_proc_end
_proc (request_write ( ))
do nr > 0 or nw > 0 -> _wait (ok_to_write) od
nw := nw + 1
_proc_end
_proc (release_write ( ))
nw := nw -1
_signal (ok_to_write)
_signal_all (ok_to_read)
_proc_end
_monitor_end
page 46
File rw_controller.m
resource main ( )
import RW_controller
process writer (i := 1 to 5)
RW_controller.request_write ( )
Update_Database ( )
RW_controller.release_write ( )
end
end
File reader_writer.sr
_monitor semaphore
op p ( ), v ( )
_body semaphore
var s:int := 0
_condvar (not_zero)
page 47
_proc (p ( ))
if s=0 -> _wait (not_zero) fi
s := s - 1
_proc_end
_proc (v ( ))
if _not_empty (not_zero) = true ->
_signal (not_zero)
[] else ->
s := s + 1
fi
_proc_end
_monitor_end
page 48
[] else -> V (s)
fi
page 49
if fork [(i-1) mod 5] = 2 ->
_signal (ok_to_eat [(i-1) mod 5] )
fi
_proc_end
_monitor_end
resource main ( )
import fork_monitor
page 50
the first equation implies ∑ fork[i] ≤ 5 and if no
philosopher is eating, then the second equation implies
∑ fork[i] = 10. The contradiction implies that the
solution does not deadlock.
page 51
barber exit
customer
_monitor (barber_shop)
op get_haircut ( ), get_next_customer ( )
op finish_cut ( )
_body (barber_shop)
var barber:int := 0, chair:int := 0, open:int := 0
_condvar (barber_available) # when barber > 0
_condvar (chair_occupied) # when chair > 0
_condvar (door_open) # when open > 0
_condvar (customer_left) # when open = 0
# called by customer
_proc (get_haircut ( ))
do barber = 0 -> _wait (barber_available) od
barber := barber -1
chair := chair + 1
_signal (chair_occupied)
do open = 0 -> _wait (door_open) od
page 52
open := open - 1
_signal (customer_left)
_proc_end
# called by barber
_proc (get_next_customer ( ))
barber : barber + 1
_signal (barber_available)
do chair = 0 -> _wait (chair_occupied) od
chair := chair - 1
_proc_end
#called by barber
_proc (finished_cut ( ))
open := open + 1
_signal (door_open)
do open > 0 -> _wait (customer_left) od
_proc_end
_monitor_end
page 53