Distributed Algorithms Ricart Agrawala Mutual Exclusion Distributed Algorithms
Distributed Algorithms - Ricart Agrawala Mutual Exclusion Distributed Algorithms Ricart Agrawala Mutual Exclusion Datum: 26. Juni 2000 Vortragende: Thomas Lehner Rene Mayrhofer Thomas Lehner, Rene Mayrhofer 2000 -06 -26
Distributed Algorithms - Ricart Agrawala Mutual Exclusion gegeben: Problemstellung - asynchrones Netzwerk - eine Ressource - mehrere konkurrierende Prozesse und deren User gewünscht: - immer nur ein Prozess greift zugleich auf Ressource zu Beispiel: Drucker Problemlösung Grundlegende Idee des Ricart Agrawala Algorithmus: - Einführung einer Critical Region - Prozesse dürfen nur aus dieser auf Ressource zugreifen - Prozesse sprechen sich untereinander ab, so dass sich immer nur einer zugleich in der Critical Region befindet exklusiver Zugriff auf Ressource Thomas Lehner, Rene Mayrhofer 2000 -06 -26
Distributed Algorithms - Ricart Agrawala Mutual Exclusion Problemlösung User-Prozess Interaktion: Einzuhaltende Bedingungen: Well-formedness: - die User-Prozess Interaktion ist wohlgeformt Mutual exclution: - es ist kein globaler Zustand erreichbar, in dem sich mehr als ein Prozess in C befindet Progress: - wenn kein Prozess in C und zumindest einer in T ist, dann muss irgendwann einer in C eintreten - wenn zumindest ein Prozess in E ist, erreicht irgendwann einer auch R Lockout-freedom: - wenn alle User C immer verlassen, dann kommt ein Prozess der in T ist auch irgendwann in C - jeder in E ist kommt auch irgendwann in R Thomas Lehner, Rene Mayrhofer 2000 -06 -26
Distributed Algorithms - Ricart Agrawala Mutual Exclusion Der Ricart Agrawala. ME Algorithmus - Jeder Prozess besitzt eine logische Uhr. Diese wird erhöht bei jedem Empfangs-/Sendeereignis und bei jeder User-Prozess Interaktion. - Es existieren die beiden Nachrichten TRY und OK. - Ein Prozess i kann nur dann in C eintreten, wenn er ein TRYBroadcast durchgeführt hat und von alle anderen Prozessen die dazugehörigen OK’s erhielt. - Ein Prozess i darf nur dann mit einem OK auf ein (“try”, c) von j antworten wenn: 1. Pi ist in E, R oder in T und das tryi wurde noch nicht versand. 2. Pi ist in T und (c, j)<(c´, i) mit (c´, “try“) ist letztes TRY von Pi 2000 -06 -26 - In allen anderen Fällen wird das OK für Pj zwischengespeichert und erst in E Thomas Lehner, Rene Mayrhofer
Distributed Algorithms - Ricart Agrawala Mutual Exclusion Beweis für Safety Beweis für Mutual Exclution durch indirekte Beweisführung: Annahme: Pi und Pj sind zu gleich in C mit (c(last tryi), i)<(c(last tryj), j) es existieren die dazugehörigen zwei TRY und OK Nachrichten, die von Pj an Pi bzw. von Pi an Pj geschickt wurden, bevor die Prozesse in C eintraten zwei Mögliche Zeitpunkte an denen das TRY von Pj bei Pi ankam: - i hat sein TRY noch nicht versendet: dann kann Pi kein TRY mit (c, i)<(c(last tryj), j) mehr broadcasten - i hat sein TRY bereits abgeschickt: dann kann Pj kein OK von Pi erhalten, da ja nach Annahme gilt (c(last tryi), i)<(c(last tryj), j) und somit Pi das OK zurückhält bis Region Ei erreicht wird Thomas Lehner, Rene Mayrhofer 2000 -06 -26
Distributed Algorithms - Ricart Agrawala Mutual Exclusion Beweis für Liveness ·Beweis für Progress: (für Region E trivial) - Der Beweis für die Region T durch indirekten Beweis: Annahme: Zum Zeitpunkt a ist zumindest ein Prozess in T und keiner erreicht je C --> es existiert ein Zeitpunkt b vor a an dem alle Prozesse in R oder in T bleiben --> es existiert ein Zeitpunkt c nach b an dem alle Prozesse in T ihre TRY versand haben und keine dieser Nachrichten mehr in den Nachrichtenkanälen ist --> für einen Pi in T gilt nun: (c(latest Tryi), i)<(c(latest Tryj), j) für alle Pj in T Da Pi nicht in C eintritt, muss es mindestens einen Pj geben dessen OK fehlt Die 2 Gründe, weshalb Pj das OK zurückhalten kann: - Pj ist in C. Widerspruch, da Pj in R oder in T ist - Pj ist in T und erhielt ein Tryj mit (c(Tryj), j)<(c(latest Tryk), k) für alle Pk in T (k j) Widerspruch, da gilt: (c(latest Tryi), i)<(c(latest Tryj), j) ·Beweis für Lockout-freedom: (für Region E trivial) - Der Beweis für die Region T durch indirekten Beweis: Annahme: Pi ist in T mit versendetem TRY und tritt nie in C ein nach dem maximal n*(c(latest tryi)-1) + i-1 mal ein Prozess in C eintrat, tritt kein weiterer Pj (j i)mehr in C ein, da dann gelten würde (c(latest tryj), j)>(c(latest tryi), i) Widerspruch zu Beweis von Progress Thomas Lehner, Rene Mayrhofer 2000 -06 -26
Distributed Algorithms - Ricart Agrawala Mutual Exclusion Formale Spezifikation - 1 Node i ( i {1, . . . , N} ): Signature: Input: tryi exiti recieve(m)j, i, m {"try", "ok"} N, 1 <= j <= N Output: criti remi send(m)i, j, m {"ok"} N, j i bcast(m)i, m {"try"} N State Variables: regioni {R, T, C, E}, initially R clocki N, initially 0 bcast-bufferi, a FIFO queue of {"try"}, initially empty for every j, 1 <= j, <= N: history(j)i, a subset of {"try", "ok"} N, initially {} for every j ¹ i: send-buffer(j)i, a FIFO queue of {"ok"}, initially empty deferred-ok(j)i, a FIFO queue of {"ok"}, initially empty Thomas Lehner, Rene Mayrhofer Transitions: tryi Effect: clocki : = clocki + 1 regioni : = T add ("try") to bcast-buffer i recieve(m, c)j, i Effect: clocki : = max(clocki, c) + 1 history(j)i : = history(j)i {(m, c)} if m = "try" and j i then if regioni {E, R} or (region i = T and bcast-buffer i contains ("try")) then add ("ok") to send-buffer(j) i else if regioni = C then add ("ok") to deferred-ok(j) i else if regioni = T and not bcast-buffer i contains ("try") if (c', i) > (c, j) with ("try", c') history(i)i and (c'' with ("try", c'') history(i)i and c'' > c') then add ("ok") to send-buffer(j) i else add ("ok") to deferred-ok(j) i 2000 -06 -26
Distributed Algorithms - Ricart Agrawala Mutual Exclusion Formale Spezifikation - 2 exiti Effect: clocki : = clocki + 1 regioni : = E for all j i for all (m, c) in deferred-ok(j) i add (m, c) to send-buffer(j) i clear deferred-ok(j) i send(m, c)i, j Precondition: m ist first on send-buffer(j) i c = clocki + 1 Effect: clocki : = clocki +1 remove first element of send-buffer(j) i bcast(m, c)i criti Precondition: m ist first on bcast-buffer i regioni = T c = clocki + 1 for such a c that ("try", c) history(i)i and (c'' with ("try", c'') Effect: history(i)i and c'' > c) clocki : = clocki +1 for all j i remove first element of bcast-buffer i ("ok", c') history(j)i with (c, i) < (c', j) Effect: clocki : = clock + 1 Tasks: regioni : = C { criti } remi Precondition: regioni = E Effect: clocki : = clocki +1 regioni = R Thomas Lehner, Rene Mayrhofer { remi } { bcast(m)i } for every j i: { send(m)i, j } 2000 -06 -26
Distributed Algorithms - Ricart Agrawala Mutual Exclusion package Mutual. Exclusion; import daj. *; import java. util. *; public class Ricart. Agrawala public static final int extends Application { PNUM = 6; DISTANCE = 70; BORDER = 40; . . public void construct() { Node[] nodes = new Node[PNUM]; int i, j; double phi, r = (PNUM * DISTANCE) / (2 * Math. PI); for (i=0; i<PNUM; i++) { phi = (double) i / PNUM * Math. PI * 2; nodes[i] = node(new Prog(i), new Integer(i). to. String(), (int) (r * Math. cos(phi) + r + BORDER), (int) (r * Math. sin(phi) + r + BORDER)); } for (i=0; i<PNUM; i++) { for (j=0; j<PNUM; j++) { link(nodes[i], nodes[j]); } } }. . } Thomas Lehner, Rene Mayrhofer 2000 -06 -26
Distributed Algorithms - Ricart Agrawala Mutual Exclusion class Prog extends Program {. . . /** the node number */ protected int index; /** the region can be either R, T, C or E */ protected int region = R; /** the current clock value */ protected int clock = 0; /** for every node, the message history */ protected Vector[] history = null; /** for every neighbour, the buffer for remembering deferred ok messages until critical region has been left */ protected Vector[] deferred_ok = null; /** the logical time of the last "try" message that has been sent */ protected Logical. Time last. Try. Time = null; /** the default constructor initializes the index and the arrays */ public Prog(int index) { this. index = index; history = new Vector[Ricart. Agrawala. PNUM]; for (int i=0; i<history. length; i++) history[i] = new Vector(); deferred_ok = new Vector[Ricart. Agrawala. PNUM]; for (int i=0; i<deferred_ok. length; i++) if (i != index) deferred_ok[i] = new Vector(); else deferred_ok[i] = null; } Thomas Lehner, Rene Mayrhofer 2000 -06 -26
Distributed Algorithms - Ricart Agrawala Mutual Exclusion public void try. Ressource() { // single actions must be atomic --> synchronize them synchronized (this) { clock++; region = T; last. Try. Time = new Logical. Time(clock, index); out(). send(new Msg(Msg. TRY, last. Try. Time)); } } public void free. Ressource() { synchronized (this) { clock++; // this does not match the formal specification - the release is // done immediately region = R; for (int i=0; i<deferred_ok. length; i++) if (i != index) { for (int j=0; j<deferred_ok[i]. size(); j++) { out(i). send((Msg) deferred_ok[i]. get(j)); } deferred_ok[i]. remove. All. Elements(); } } } public void ressource. Available() { // for testing purposes there is no user to ne notified } public void ressource. Freed() { // for testing purposes there is no user to ne notified } Thomas Lehner, Rene Mayrhofer 2000 -06 -26
Distributed Algorithms - Ricart Agrawala Mutual Exclusion public void main() { Random rand = new Random(); Global. Assertion safety = new Critical. Region. Conflict(), liveness = new Critical. Region. Lockout(); while (true) { assert(safety); assert(liveness); /* first the tree construction routines */ int received = in(). select(2); if (received >= 0) { synchronized (this) { Msg msg = (Msg) in(received). receive(); if (msg. time. clock > clock) clock = msg. time. clock; clock++; history[received]. add(msg); // respond to try requests from other nodes if (msg. type == Msg. TRY && received != index) handle. Try. Message(received, msg); // check if the critical region can be entered now if (region == T && check. Ok. Msgs. Received()) { clock++; region = C; // the last try is invalid now last. Try. Time = null; } } } // simulate the user here. . . } } Thomas Lehner, Rene Mayrhofer 2000 -06 -26
Distributed Algorithms - Ricart Agrawala Mutual Exclusion private void handle. Try. Message(int received, Msg msg) { Msg ack. Msg = new Msg(Msg. OK, new Logical. Time(clock, index)); if (region == R /*|| region == E*/) out(received). send(ack. Msg); else if (region == C) deferred_ok[received]. add(ack. Msg); else if (region == T) { if (last. Try. Time != null && msg. time. less. Than(last. Try. Time)) out(received). send(ack. Msg); else deferred_ok[received]. add(ack. Msg); } } private boolean check. Ok. Msgs. Received() { boolean received. Ok. Msgs = true; for (int i=0; i<history. length; i++) { if (i != index) { int j = history[i]. size() - 1; while (j >= 0 && ((Msg) history[i]. get(j)). type != Msg. OK) j--; if (j >= 0) { Msg last. Msg = (Msg) history[i]. get(j); if (! last. Try. Time. less. Than(last. Msg. time)) received. Ok. Msgs = false; } else received. Ok. Msgs = false; } } return received. Ok. Msgs; } } Thomas Lehner, Rene Mayrhofer 2000 -06 -26
Distributed Algorithms - Ricart Agrawala Mutual Exclusion class Logical. Time { /** the clock value */ public int clock; /** for equal clock values the sender process's index is compared */ public int process; public Logical. Time(int clock, int process) { this. clock = clock; this. process = process; } public boolean equals(Object o) { if (o instanceof Logical. Time && ((Logical. Time) o). clock == clock && ((Logical. Time) o). process == process) return true; else return false; } public boolean less. Than(Logical. Time t) { if (clock < t. clock || (clock == t. clock && process < t. process)) return true; else return false; } } Thomas Lehner, Rene Mayrhofer 2000 -06 -26
Distributed Algorithms - Ricart Agrawala Mutual Exclusion class Critical. Region. Conflict extends Global. Assertion { private Vector procs. In. CR = new Vector(); public boolean assert(Program progs[]) { int num. Of. Procs. In. CR = 0; procs. In. CR. remove. All. Elements(); for (int i=0; i<progs. length; i++) { if (((Prog) progs[i]). region == Prog. C) { num. Of. Procs. In. CR++; procs. In. CR. add(new Integer(i)); } } return num. Of. Procs. In. CR <= 1; } public String get. Text() { String text = "Processes in the critical region: "; for (int i=0; i<procs. In. CR. size(); i++) text += procs. In. CR. get(i) + " "; return text; } } Thomas Lehner, Rene Mayrhofer 2000 -06 -26
Distributed Algorithms - Ricart Agrawala Mutual Exclusion class Critical. Region. Lockout extends Global. Assertion { private Logical. Time[] try. Times = new Logical. Time[Ricart. Agrawala. PNUM]; private int proc. In. CR = -1, proc. Trying. Longer = -1; public Critical. Region. Lockout() { for (int i=0; i<try. Times. length; i++) try. Times[i] = null; } public boolean assert(Program progs[]) { for (int i=0; i<progs. length; i++) if (((Prog) progs[i]). region == Prog. T) try. Times[i] = ((Prog) progs[i]). last. Try. Time; // Now check when a process is in the CR, if another one is still // trying but started to try earlier. This should not happen. for (int i=0; i<progs. length; i++) if (((Prog) progs[i]). region == Prog. C) { for (int j=0; j<progs. length; j++) { if (((Prog) progs[j]). region == Prog. T && try. Times[j]. less. Than(try. Times[i])) { proc. In. CR = i; proc. Trying. Longer = j; return false; } } } return true; } } Thomas Lehner, Rene Mayrhofer 2000 -06 -26
- Slides: 16