master-degree-notes/Concurrent Systems/notes/Lezione2.md

4.4 KiB

Peterson's algorithm cost O(n^2) A first way to reduce this cost is by using a tournament of MUTEX between pairs of processes: !Pasted image 20250304082459.png

Of course this is a binary tree, and the height of a binary tree is logaritmic to the number of leaves. A process then wins after \lceil \log_{2}n \rceil competitions \to O(\log n) cost.

But we can do better. Let's see an idea of a constant-time algorithm.

Initialize Y at ⊥, X at any value (e.g., 0)

lock(i) :=
	x <- i
	if Y != ⊥ then FAIL
	else Y <- i
	if X = i then return
	else FAIL

 unlock(i) :=
	 Y <- ⊥
	 return

Problems:

  • we don't want the FAIL
  • it is possible to have an execution where nobody accesses its CS, if repeated forever it entails a deadlock
Initialize Y at ⊥, X at any value (e.g., 0)


lock(i) :=
	* FLAG[i] <- up
	X <- i
	if Y ≠ ⊥ then FLAG[i] <- down
		wait Y = ⊥
		goto *
	else Y <- i
	
	if X = i then return
	else FLAG[i] <- down
	
	∀j.wait FLAG[j] = down
	
	if Y = i then return
	else wait Y = ⊥
	
	goto *

unlock(i) :=
	Y <- ⊥
	FLAG[i] <- down
	return
MUTEX proof

How can pi enter its CS? !Pasted image 20250304084537.png

!Pasted image 20250304084901.png

Deadlock freedom

Let p_i invoke lock

  • If it eventually wins -> √
  • If it is blocked forever, where can it be blocked?
    1. In the second wait Y = ⊥
      • in this case, it read a value in Y different from i
      • there is a p_h that wrote Y after p_i
      • let us consider the last of such p_h \to it will eventually win
    2. In the ∀j.wait FLAG[j] = down
      • this wait cannot block a process forever
      • if pj doesn't lock, it flag is down
      • if pj doesn't find Y at ⊥, it puts its flag down
      • if pj doesn't find X at j, it puts its flag down, otherwise pj enters its CS and eventually unlocks (flag down)
      1. In the first wait Y = ⊥
      • since pj read a value different from ⊥, there is at least one pk that wrote Y before (but has not yet unlocked)
      • if p_k eventually enters its CS -> ok, otherwise it must be blocked forever as well. Where?
        • In the second wait Y = ⊥: but then there exists a p_h that eventually enters its CS -> good
        • In the ∀j.wait FLAG[j]=down: this wait cannot block a process forever

!Pasted image 20250304090219.png

esercizio: prova che NON soddisfa starvation freedom

From deadlock freedom to bounded bypass

-> Round Robin algorithm

Let DLF be any deadlock free protocol for MUTEX. Let's see how we can make it satisfy bounded bypass:

lock(i) :=
	FLAG[i] <- up
	wait (TURN = i OR FLAG[TURN] = down)
	DLF.lock(i)
	return

unlock(i) :=
	FLAG[i] <- down
	if FLAG[TURN] = down then
		TURN <- (TURN + 1) mod n
	DLF.unlock(i)
	return
Is it deadlock free?

Since DLF is deadlock free, it is sufficient to prove that at least one process invokes DLF.lock. If TURN = k and p_k invoked lock, then it finds TURN = k and exits its wait. Otherwise, any other process will find FLAG[TURN] = down and exits from its wait.

Lemma 1: if TURN = i and FLAG[i] = up then p_i enters the CS in at most n-1 iterations

Observation 1: TURN changes only when FLAG[i] is down (after pi has completed its CS)

Observation 2: FLAG[i] = up -> either pi is in its CS or pi is competing for its CS -> it eventually invokes (if not already) DLF.lock

Observation 3: if p_j invokes lock after that FLAG[i] is set, p_j blocks in its wait

Let Y be the set of processes competing for the CS (suspended on the DLF.lock)

  • because of Observation 2, i \in Y
  • because of Observation 3, once FLAG[i] is set, Y cannot grow anymore
  • because DLF is deadlock free, eventually one p_{y} \in Y wins if y = i.
    • if y = i we are done
    • otherwise, Y shrinks by one. And because of Observation 1, TURN and FLAG[TURN] don't change, so p_y cannot enter Y again.
  • Iterating this reasoning we can see that p_i will eventually win, and the worst case is when is the last winner.

Lemma 2: If FLAG[i] = up, then TURN is set to i in at most (n-1)^2 iterations.

If TURN=i when FLAG[i] is set, done By Deadlock freedom of RR, at least one process eventually unlocks

  • If FLAG[TURN] = down, then TURN is increased. Otherwise, by Lemam 1, p_{TURN} wins in at most n-1 iterations and increases TURN.
  • If now TURN = i then we are done. Otherwise, we repeat this reasoning.

The worst case is when TURN = i+1 mod n when FLAG[i] is set.

!Pasted image 20250304093223.png