4 KiB
Aravind’s algorithm
Problem with Lamport's "Bakery" algorithm: registers must be unbounded (every invocation of lock potentially increases the counter by 1 -> domain of the registers is all natural numbers!)
For all processes, we have a FLAG and a STAGE (both binary MRSW) and a DATE (MRMW) register that ranges from 1 to 2n.
For all i, initialize
FLAG[i] to down
STAGE[i] to 0
DATE[i] to i
lock(i) :=
FLAG[i] <- up
repeat
STAGE[i] <- 0
wait (foreach j != i, FLAG[j] = down OR DATE[i] < DATE[j])
STAGE[i] <- 1
until foreach j != i, STAGE[j] = 0
unlock(i) :=
tmp <- max_j{DATE[j]}+1
if tmp >= 2n
then foreach j, DATE[j] <- j
else DATE[i] <- tmp
STAGE[i] <- 0
FLAG[i] <- down
MUTEX proof
Theorem: if p_i
is in the CS, then p_j
cannot simultaneously be in the CS.
Proof: by contradiction.
Let's consider the execution of p_i
leading to its CS:
!
Corollary (of the MUTEX proof): DATE is never written concurrently.
Bounded bypass proof
Lemma 1: exactly after n CSs there is a reset of DATE. Proof:
- the first CS leads
max_j{DATE[j]}
to n+1 - the seconds CS leads ... to n+2
- ...
- the n-th read leads ... to n+n = 2n -> RESET
Lemma 2: there can be at most one reset of DATE during an invocation of a lock Proof:
- let
p_i
invoke lock, if no reset occurs, ok - otherwise, let us consider the moment in which a reset occurs
- if pi is the next process that enters the CS, ok
- Otherwise let
p_j
be the process that enters; its next date isn+1 > DATE[i]
p_{j}
cannot surpassp_i
again (before a RESET)
- The worst case is then all processes perform lock together and
i = n
(i am process n)- all
p_{1}\dots p_{n}
surpassp_{n}
- then
p_n
enters and it resets the DATE in its unlock- only 1 reset and it is the worst case!
- all
Theorem: the algorithm satisfies bounded bypass with bound 2n-2
.
Proof:
!
so by this, the very worst possible case is that my lock experiences that.
It looks like I can experience at most 2n-1
other critical sections, but it is even better, let's see:
p_n
invokes lock alone, completes its CS (the first after the reset) and its new DATE is n+1- all processes invoke lock simultaneously
p_{n}
has to wait all other processes to complete their CSs- when
p_{n-1}
completes its CS, its new DATE will ben+(n-1)+1=2n
-> RESET - now all
p_{1}\dots p_{n-1}
invoke lock again and complete their CSs (after thatp_i
completes its CS, now it hasDATE[i] <- n+i
, because as everyone invoked lock after the RESET, max date wasn
) - so
p_n
has to wait n-1 CSs for the reset, and another n-1 CSs before entering again. Literally the worst case is when the process is the first of the first round, and the last of the last round.
Improvement of Aravind’s algorithm
unlock(i) :=
∀j≠i.if DATE[j] > DATE[i] then
DATE[j] <- DATE[j]-1
DATE[i] <- n
STAGE[i] <- 0
FLAG[i] <- down
Since the LOCK is like before, the revised protocol satisfies MUTEX. Furthermore, you can prove that it satisfies bounded bypass with bound n-1 -> EXERCISE!
Let's remember ourselves how is the locking function defined:
lock(i) :=
FLAG[i] <- up
repeat
STAGE[i] <- 0
wait (foreach j != i, FLAG[j] = down OR DATE[i] < DATE[j])
STAGE[i] <- 1
until foreach j != i, STAGE[j] = 0
p_n
invokes lock alone, completes its CS and soDATE[n] = n
- then as DATE is either set to n or decreased, for each i,
DATE[i] < n
- scenario 1: every other
p_i
keep invoking lock again immediately after the unlock- every time some process exits the CS,
DATE[n]
is decreased - after
n-1
turns,DATE[n]
will haveDATE[n] = 1
, with every otherDATE[i] > 1, i!=n
-> ️✅
- every time some process exits the CS,
- scenario 2: not every process invokes the lock
- eventually, more than one process will have its DATE set to 0
- but there will still be at most
n-1
processesp_i
withDATE[i] < DATE[n]
, this ensures that aftern-1
steps, every other processp_i
will haveDATE[i] > DATE[n]
-> ✅