- remember
- interference and mis-synchronization lead to undesirable results
- atomicity and synchronization limit execution traces to desirable results
- atomicity
- atomicity represents indivisible execution - within the concurrent
computation
- hardware only provides fine-grain atomicity - portability assumptions
- coarser-grained atomicity requires programmer effort - sometimes
languages help
- a critical section (region) models atomicity
- a fence with two gates around an atomic action
- only one computation at a time is allowed in.
- four critical section properties
- mutual exclusion (mutex) - no sharing begs the atomicity question
- deadlock free - one competing process always wins
- low delay - non-competing processes don't wait
- fairness - every competing process eventually wins
- implementing atomicity
- assume a concurrent computation of two sequential computations SC1 and SC2
while (true)
code accessing only locals
< code accessing locals and globals >
code accessing only locals
- general approach - shrink the angle brackets
- the smaller the angle brackets, the more concurrency
- smaller angle brackets are easier to implement
while (true)
code accessing only locals
< entry protocol >
code accessing locals and globals
< exit protocol >
code accessing only locals
- approaches
- disjoint variables - not practical; each tries to communicate with
the other
- weakened assertions - possible but unlikely; must enforce atomicity
(but, readers atomicity)
- synchronization - begs the question.
- that leaves global properties
- the mutex (mutual exclusion) global property
- the boolean global ini is true if and only if SCi is in
the critical section
- the global mutex property is
not (
in1 and
in2)
- implementing critical sections
- first cut
- try the obvious - if one sequential computation wants in and the
other isn't in, then enter
-
wait !
inj ;
ini = true
- tie breaker (peterson's)
- what's wrong with the obvious - interference
-
while !
ini ;
inj = true
- use write-local, read-global variables to avoid interference -
violates the global invariant, deadlocks
- inj
= true ; while !
ini
- deadlock is easy to break - order
-
last = i ;
ini = true ; < wait !
inj or last = j >
- at least once is violated - atomicity required
- what does it mean for both to be in the critical section
-
last = i and last = j
- impossible
- implement the
wait
with a while
- n-party versions are complicated
- ticketing
- take a number and wait your turn
< turn[i] = number ; number++ > // 1
< wait turn[i] == next > // 2
critical section
< next = next + 1 > // 3
- 2 becomes true and stays true - weak fairness
- global invariant
- next is positive
- if CSi in cr, then
turn[i] = next
- nonzero turn values are unique
- implementation
- 2 obeys at most one
- 3 is executed atomically (careful!)
- 1 is a problem - atomicity hides interference (maintaining
uniqueness), multiple critical references (increasing
number
)
- use a second critical section algorithm to implement 1 - peterson's
- naturally n-party, but expensive for small values of n
- bakery numbering
- take a number, wait your turn
- take a number larger than all current waiters
- wait until your number is smallest among the waiters
- global invariant
- each waiter's number is unique
- the computation in the critical section has the smallest number among
the waiters
- implementation
- need to ignore the non-waiters - low numbers that don't count
< number[i] = max(number[1..n]) + 1 > // 1
in[i] = true
< for j = 1 to n
if i != j
while in[j] and number[i] > number[j] { } > // 2
critical section
in[i] = false
- these are huge, expensive atomic actions
- for 2, numbers added after i are larger than
numbers[i]
- no interference
- for 1, atomicity provides uniqueness
- recover uniqueness by breaking ties with the computation id
- a more complicated ticket number that can't tie -
(number[i], i) > (number[j], j)
This page last modified on 22 June 2002.