Академический Документы
Профессиональный Документы
Культура Документы
Tom Ridge
1 Peterson’s Algorithm
1.1 Peterson’s Algorithm
Peterson’s algorithm [Pet81] is designed to ensure mutual exclusion between
two processes without any special hardware support.
Peterson’s algorithm has been formalised and verified several times1 .
Although the algorithm is essentially finite state, and therefore susceptible
to model checking, we provide an invariant style proof. Invariant style proofs
illustrate techniques that are usable for problems that do not fall to model
checking techniques. They can also provide important information to justify
intuitive notions of why an algorithm is correct, and this knowledge may
serve when tackling more complicated algorithms. Finally, invariant style
proofs are often more elegant than model checking proofs.
(*
ocamlmktop -I +threads -o ocamlthread unix.cma threads.cma
ocamlthread -I +threads
*)
let ps =
let turn = ref false in
let trys =
let try_f = ref false in
let try_t = ref false in
fun x -> if x then try_t else try_f in
let p =
fun id ->
let rec loop = fun () ->
Thread.delay (Random.float 1.0) (* non-crit region - do whatever *)
; (trys id) := true (* set trying flag *)
1
e.g. Coq verification at http://coq.inria.fr/contribs/mutual-exclusion.html
1
; turn := not id (* set turn flag *)
; (let rec test =
(fun x -> if (!turn = id) or (not (!(trys (not id)))) then () else test ())
in test ()) (* looping in test *)
; print_string ("Crit "^(string_of_bool id)); print_newline()
; Thread.delay (Random.float 1.0) (* crit region, do whatever *)
; print_string ("Exit "^(string_of_bool id)); print_newline()
; (trys id) := false (* exit crit by unsetting trying flag *)
; loop ()
in
loop () in
[Thread.create p false; Thread.create p true]
;;
• Non-critical (in this case, we delay the process, but in general it might
be doing anything other than touching the global state).
• Testing whether the turn flag has been set to its own process id, or
whether the other process has its try flag set to false.
• Critical (in this case, we print some trace output and delay the pro-
cess, but in general it might be doing anything other than touching
the global state).
Crit false
Exit false
Crit true
Exit true
2
Crit false
Exit false
Crit true
Exit true
Crit false
Exit false
Crit true
Exit true
Crit false
Exit false
Crit true
Exit true
Crit false
Exit false
Crit true
Exit true
Crit false
Exit false
Crit true
Exit true
Crit false
Exit false
Crit false
Exit false
We then define a type alias to distinguish try variables from other booleans.
3
The process state consists of a program counter, and a try variable.
let (f ,turn) = s in
let (f ′,turn ′) = s ′ in
(∗ get i ′s processState ∗)
let (ipc,itry) = f i in
let (ipc ′,itry ′) = f ′ i in
(∗ NonCrit, looping ∗)
((ipc = NonCrit) & ((ipc ′,itry ′,turn ′) = (ipc,itry,turn)))
(∗ SetTry to SetTurn ∗)
| ((ipc = SetTry) & ((ipc ′,itry ′,turn ′) = (SetTurn,True,turn)))
(∗ SetTurn to Test ∗)
| ((ipc = SetTurn) & ((ipc ′,itry ′,turn ′) = (Test,itry,j )))
4
∼
| ((ipc = Test) & ((jtry = True) & (turn = i)) & ((ipc ′,itry ′,turn ′) = (ipc,itry,turn)))
(∗ Test to Crit ∗)
| ((ipc = Test) & ((jtry = False) | (turn = i)) & ((ipc ′,itry ′,turn ′) = (Crit,itry,turn)))
(∗ Crit, looping ∗)
| ((ipc = Crit) & ((ipc ′,itry ′,turn ′) = (ipc,itry,turn)))
(∗ Crit to Exit ∗)
| ((ipc = Crit) & ((ipc ′,itry ′,turn ′) = (Exit,itry,turn)))
(∗ Exit to NonCrit ∗)
| ((ipc = Exit) & ((ipc ′,itry ′,turn ′) = (NonCrit,False,turn)))
5
let (jpc,jtry) = f j in
∼
((ipc = Crit) & (jpc = Crit))))
))
6
In order to obtain our mutual exclusion property, we strengthen this
property slightly as follows.
))
To see this is true, note that j’s transition from Test to Crit is not
allowed, because by the previous lemma, turn is set for i.
The mutual exclusion property is a direct corollary, since if both pro-
cesses are in Crit, then turn is set for both of them, which is a contradiction.
References
[Pet81] Gary L. Peterson. Myths about the mutual exclusion problem. In-
formation Processing Letters, 12(3):115-116, June 1981.