1 / 16

Distributed Algorithms - Ricart Agrawala Mutual Exclusion Datum: 26. Juni 2000 Vortragende:

Distributed Algorithms - Ricart Agrawala Mutual Exclusion Datum: 26. Juni 2000 Vortragende: Thomas Lehner Rene Mayrhofer. Problemstellung. gegeben: - asynchrones Netzwerk - eine Ressource - mehrere konkurrierende Prozesse und deren User gewünscht:

kay
Download Presentation

Distributed Algorithms - Ricart Agrawala Mutual Exclusion Datum: 26. Juni 2000 Vortragende:

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Distributed Algorithms - Ricart Agrawala Mutual Exclusion Datum: 26. Juni 2000 Vortragende: Thomas Lehner Rene Mayrhofer

  2. Problemstellung gegeben: - 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

  3. 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 der in E ist kommt auch irgendwann in R

  4. Der Ricart AgrawalaME 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 TRY-Broadcast 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 - In allen anderen Fällen wird das OK für Pj zwischengespeichert und erst in E an Pj versand.

  5. 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

  6. 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

  7. 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 Transitions: tryi Effect: clocki := clocki + 1 regioni := T add ("try") to bcast-bufferi 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 (regioni = T and bcast-bufferi 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-bufferi 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

  8. 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 criti Precondition: regioni = T for such a c that ("try", c)  history(i)i and (c'' with ("try", c'')  history(i)i and c'' > c) for all j  i  ("ok", c')  history(j)i with (c, i) < (c', j) Effect: clocki := clock + 1 regioni := C remi Precondition: regioni = E Effect: clocki := clocki +1 regioni = R 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 Precondition: m ist first on bcast-bufferi c = clocki + 1 Effect: clocki := clocki +1 remove first element of bcast-bufferi Tasks: { criti } { remi } { bcast(m)i } for every j  i: { send(m)i, j }

  9. package MutualExclusion; import daj.*; import java.util.*; public class RicartAgrawala extends Application { public static final int PNUM = 6; public static final int DISTANCE = 70; public static final int 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).toString(), (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]); } } } .... }

  10. 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 LogicalTime lastTryTime = null; /** the default constructor initializes the index and the arrays */ public Prog(int index) { this.index = index; history = new Vector[RicartAgrawala.PNUM]; for (int i=0; i<history.length; i++) history[i] = new Vector(); deferred_ok = new Vector[RicartAgrawala.PNUM]; for (int i=0; i<deferred_ok.length; i++) if (i != index) deferred_ok[i] = new Vector(); else deferred_ok[i] = null; }

  11. public void tryRessource() { // single actions must be atomic --> synchronize them synchronized (this) { clock++; region = T; lastTryTime = new LogicalTime(clock, index); out().send(new Msg(Msg.TRY, lastTryTime)); } } public void freeRessource() { 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].removeAllElements(); } } } public void ressourceAvailable() { // for testing purposes there is no user to ne notified } public void ressourceFreed() { // for testing purposes there is no user to ne notified }

  12. public void main() { Random rand = new Random(); GlobalAssertion safety = new CriticalRegionConflict(), liveness = new CriticalRegionLockout(); 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) handleTryMessage(received, msg); // check if the critical region can be entered now if (region == T && checkOkMsgsReceived()) { clock++; region = C; // the last try is invalid now lastTryTime = null; } } } // simulate the user here ... } }

  13. private void handleTryMessage(int received, Msg msg) { Msg ackMsg = new Msg(Msg.OK, new LogicalTime(clock, index)); if (region == R /*|| region == E*/) out(received).send(ackMsg); else if (region == C) deferred_ok[received].add(ackMsg); else if (region == T) { if (lastTryTime != null && msg.time.lessThan(lastTryTime)) out(received).send(ackMsg); else deferred_ok[received].add(ackMsg); } } private boolean checkOkMsgsReceived() { boolean receivedOkMsgs = 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 lastMsg = (Msg) history[i].get(j); if (! lastTryTime.lessThan(lastMsg.time)) receivedOkMsgs = false; } else receivedOkMsgs = false; } } return receivedOkMsgs; } }

  14. class LogicalTime { /** the clock value */ public int clock; /** for equal clock values the sender process's index is compared */ public int process; public LogicalTime(int clock, int process) { this.clock = clock; this.process = process; } public boolean equals(Object o) { if (o instanceof LogicalTime && ((LogicalTime) o).clock == clock && ((LogicalTime) o).process == process) return true; else return false; } public boolean lessThan(LogicalTime t) { if (clock < t.clock || (clock == t.clock && process < t.process)) return true; else return false; } }

  15. class CriticalRegionConflict extends GlobalAssertion { private Vector procsInCR = new Vector(); public boolean assert(Program progs[]) { int numOfProcsInCR = 0; procsInCR.removeAllElements(); for (int i=0; i<progs.length; i++) { if (((Prog) progs[i]).region == Prog.C) { numOfProcsInCR++; procsInCR.add(new Integer(i)); } } return numOfProcsInCR <= 1; } public String getText() { String text = "Processes in the critical region: "; for (int i=0; i<procsInCR.size(); i++) text += procsInCR.get(i) + " "; return text; } }

  16. class CriticalRegionLockout extends GlobalAssertion { private LogicalTime[] tryTimes = new LogicalTime[RicartAgrawala.PNUM]; private int procInCR = -1, procTryingLonger = -1; public CriticalRegionLockout() { for (int i=0; i<tryTimes.length; i++) tryTimes[i] = null; } public boolean assert(Program progs[]) { for (int i=0; i<progs.length; i++) if (((Prog) progs[i]).region == Prog.T) tryTimes[i] = ((Prog) progs[i]).lastTryTime; // 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 && tryTimes[j].lessThan(tryTimes[i])) { procInCR = i; procTryingLonger = j; return false; } } } return true; } }

More Related