Die Präsentation wird geladen. Bitte warten

Die Präsentation wird geladen. Bitte warten

Kapitel 6 Nebenläufigkeit und wechselseitiger Ausschluss

Ähnliche Präsentationen


Präsentation zum Thema: "Kapitel 6 Nebenläufigkeit und wechselseitiger Ausschluss"—  Präsentation transkript:

1 Kapitel 6 Nebenläufigkeit und wechselseitiger Ausschluss
Systeme 1 Kapitel 6 Nebenläufigkeit und wechselseitiger Ausschluss WS 2009/10

2 Threads Die Adressräume verschiedener Prozesse sind
getrennt und geschützt gegen den Zugriff anderer Prozesse. Threads sind „leichtgewichtige Prozesse“ kein gegenseitiger Schutz somit mit gemeinsamen Adressraum (aber eigener Kellerspeicher (Stack)) teilen geöffnete Dateien und andere Ressourcen Annahme: Threads kooperieren untereinander weniger Overhead im Vergleich zu (schwergewichtigen) Prozessen WS 2009/10

3 Nebenläufigkeit Nebenläufigkeit = „potentieller Parallelismus“
Nebenläufige Prozesse können parallel auf mehreren Prozessoren ausgeführt werden. Sie können aber auch „pseudo-parallel“ auf einem Prozessor ausgeführt werden. Grundlegende Fragestellungen: Zugriff auf gemeinsame Ressourcen? Koordination, Kommunikation Bei Zugriff auf gemeinsame Ressourcen muss häufig wechselseitiger Ausschluss garantiert werden! Zum Beispiel geteilter Speicher bei Threads WS 2009/10

4 Beispiel Annahme: 2 Threads führen (u.a.) diesen Code aus.
void echo() { chin = getchar(); /* Zeichen einlesen, speichern in Variable chin */ putchar (chin); /* Zeichen ausgeben */ } Annahme: 2 Threads führen (u.a.) diesen Code aus. chin liegt im gemeinsam genutzten Speicherbereich WS 2009/10

5 Beispiel Mögliche Ausführungsfolge:
void echo() { chin = getchar(); /* Zeichen einlesen, speichern in Variable chin */ putchar (chin); /* Zeichen ausgeben */ } Mögliche Ausführungsfolge: Thread 1 liest Zeichen, wird unterbrochen -> Thread 2 z.B. T1: chin = 'a'; Thread 2 führt Prozedur komplett aus. z.B. T2: chin = 'b'; Ausgabe: 'b' Thread 1 führt Rest der Prozedur aus. T1: Ausgabe: 'b', da chin jetzt b (gemeinsam genutzter Speicher) WS 2009/10

6 Nebenläufigkeit Grundlegende Fragen bei Nebenläufigkeit
Betriebssystem muss Ressourcen der aktiven Prozesse verwalten. OS muss wechselseitigen Ausschluss bei gemeinsamen Ressourcen garantieren können. Die Korrektheit des Ergebnisses muss unabhängig von der relativen Ausführungsgeschwindigkeit der einzelnen Prozesse sein. 3 Kontrollprobleme Wechselseitiger Ausschluss, d.h. jeweils nur ein Prozess im „kritischen Abschnitt“ (= der Teil des Programms, der auf gemeinsame, exklusive Ressourcen zugreift) Verhindere Deadlocks (Blockierung aller Prozesse) Verhindere Livelocks (obwohl ein Prozess nicht blockiert ist, geht sein Ablauf nie voran.) WS 2009/10

7 Anforderungen an wechselseitigen Ausschluss
Höchstens ein Prozess im kritischen Abschnitt. Jeder Prozess hält sich nur endliche Zeit im kritischen Abschnitt auf. Wenn ein Prozess in den kritischen Abschnitt will, so muss er nur endliche Zeit darauf warten. Wenn kein Prozess im kritischen Abschnitt ist, so wird ein interessierter Prozess ohne Verzögerung akzeptiert. Alles funktioniert unabhängig von der relativen Ausführungsgeschwindigkeit der Prozesse. WS 2009/10

8 Softwarelösungen: Versuch 1
Voraussetzung 2 Prozesse konkurrieren um eine Ressource Beide Prozesse können auf eine gemeinsame Variable turn zugreifen und über diese kommunizieren. turn ist mit beliebigem Wert initialisiert (z.B. turn = 0). /* Prozess 0 */ wiederhole { solange (turn ≠ 0) (*) tue nichts; /* kritischer Abschnitt */ turn := 1; /* nichtkrit. Abschnitt */ } /* Prozess 1 */ wiederhole { solange (turn ≠ 1) tue nichts; /* kritischer Abschnitt */ turn := 0; (**) /* nichtkrit. Abschnitt */ } WS 2009/10

9 Softwarelösungen: Versuch 1
Satz: Es sind nie zwei Prozesse gleichzeitig im kritischen Abschnitt. Beweis: Angenommen es gibt einen Zeitpunkt, zu dem beide Prozesse im kritischen Abschnitt sind. Es muss also einen Zeitpunkt t1 geben, zu dem ein Prozess im kritischen Abschnitt ist (z.B. Prozess 1) und der andere Prozess (Prozess 0) betritt gerade den kritischen Abschnitt. D.h. Prozess 0 verlässt die „solange“ Schleife (*) wegen turn = 0. Es muss einen Zeitpunkt t0 gegeben haben, zu dem der Prozess 1 zum letzten Mal die „solange“ Schleife verlassen und den kritischen Abschnitt betreten hat. D.h. zum Zeitpunkt t0 muss turn = 1 gegolten haben. WS 2009/10

10 Softwarelösungen: Versuch 1
Beweis Fortsetzung: Dann muss aber zwischen t0 und t1 turn auf 0 gesetzt worden sein. turn = 0 kann aber nur bei der Initialisierung oder durch Prozess 1 an der Stelle (**) (nach dem kritischen Abschnitt) erfolgt sein. Zwischen t0 und t1 ist Prozess 1 die ganze Zeit im kritischen Abschnitt (nach Annahme). D.h. turn = 0 kann nicht erfolgt sein! WS 2009/10

11 Softwarelösungen: Versuch 1
Analyse Vorteil: Wechselseitiger Ausschluss ist garantiert. Nachteil: „Busy waiting“ = aktives Warten („solange (turn ≠ 0) tue nichts;”) Verschwendung von Rechenzeit beim Warten Nur abwechselnder Zugriff auf kritischen Abschnitt WS 2009/10

12 Softwarelösungen: Versuch 1
Beispiel für kritische Situation Prozess 0 ist schnell, Prozess 1 ist sehr langsam z.B. sehr langer, nicht kritischer Abschnitt (*) /* Prozess 0 */ wiederhole { solange (turn ≠ 0) tue nichts; /* kritischer Abschnitt */ turn := 1; /* nichtkrit. Abschnitt */ } /* Prozess 1 */ wiederhole { solange (turn ≠ 1) tue nichts; /* kritischer Abschnitt */ turn := 0; /* nichtkrit. Abschnitt */(*) } WS 2009/10

13 Softwarelösungen: Versuch 1
Ungünstiges Szenario Prozess 0 (schnell) geht in kritischen Abschnitt und setzt anschließend turn = 1. Dann geht Prozess 1 in den kritischen Abschnitt und setzt anschließend turn = 0. Prozess 0 geht in den nicht kritischen Abschnitt (schnell) dann in den kritischen Abschnitt und setzt turn = 1 und bearbeitet anschließend den nicht kritischen Abschnitt (schnell). Prozess 1 bearbeitet währenddessen immer noch seinen nicht kritischen Abschnitt. Prozess 0 muss jetzt so lange warten, bis Prozess 1 seinen (langen) nicht kritischen Abschnitt beendet hat, seinen kritischen Abschnitt bearbeitet hat und turn = 0 setzt. WS 2009/10

14 Softwarelösungen: Versuch 1
Anforderungen an wechselseitigen Ausschluss Wenn kein Prozess im kritischen Abschnitt ist, so wird ein interessierter Prozess ohne Verzögerung akzeptiert. Hier: Prozess 1 will nicht den kritischen Abschnitt. Prozess 0 will in den kritischen Abschnitt, muss aber warten. Wiederspruch zu Anforderung 4.) WS 2009/10

15 Softwarelösungen: Versuch 2
Jetzt 2 gemeinsame Variablen zur Kommunikation: Prozess 0 schreibt auf flag[0], liest beide Prozess 1 schreibt auf flag[1], liest beide Bedeutung von flag[i] = true: Prozess i will in den kritischen Abschnitt Initialisierung: flag[0] := false; flag[1] := false; /* Prozess 0 */ wiederhole { solange (flag[1] = true) tue nichts; flag[0] := true; /* kritischer Abschnitt */ flag[0] := false; /* nichtkrit. Abschnitt */ } /* Prozess 1 */ wiederhole { solange (flag[0] = true) tue nichts; flag[1] = true; /* kritischer Abschnitt */ Flag[1] := false; /* nichtkrit. Abschnitt */ } WS 2009/10

16 Softwarelösungen: Versuch 2
Vorteil: Auch nicht-alternierender Zugriff auf kritischen Abschnitt Nachteil: „Busy waiting“ („solange (flag[i] = true) tue nichts;”) Wechselseitiger Ausschluss nicht garantiert!! Beispiel für Fehlersituation : flag[0] = flag[1] = false Prozess 0 schließt Schleife („solange (flag[1] = true) tue nichts;”) ab, gibt CPU ab. Prozess 1 schließt Schleife („solange (flag[0] = true) tue nichts;”) ab. Jetzt können beide Prozesse ungehindert den kritischen Abschnitt betreten: Prozess 1 betritt kritischen Abschnitt, gibt CPU ab. Prozess 0 betritt kritischen Abschnitt. WS 2009/10

17 Softwarelösungen: Versuch 3
Anforderung des kritischen Abschnittes wird vorgezogen, um das gezeigte Problem zu verhindern: Versuch 2 ging schief, weil die Anforderung für die kritische Region zu spät erfolgte. Vertausche Reihenfolge von (**) nach (*) /* Prozess 0 */ wiederhole { flag[0] := true; (*) solange (flag[1] = true) tue nichts; (**) /* kritischer Abschnitt */ flag[0] := false; /* nichtkrit. Abschnitt */ } /* Prozess 1 */ wiederhole { flag[1] = true; solange (flag[0] = true) tue nichts; /* kritischer Abschnitt */ Flag[1] := false; /* nichtkrit. Abschnitt */ } WS 2009/10

18 Softwarelösungen: Versuch 3
Vorteil: Auch nicht-alternierender Zugriff auf kritischen Abschnitt Wechselseitiger Ausschluss garantiert! Nachteil: „Busy waiting“ („solange (flag[i] ≠ true) tue nichts;”) Es kann aber trotzdem ein Problem auftreten: flag[0] = flag[1] = false Prozess 0 setzt flag[0] := true und gibt CPU ab Prozess 1 setzt flag[1] := true Jetzt werden beide Prozesse ihre Schleife „solange (flag[i] ≠ true) tue nichts;” nie verlassen! Eine solche Situation nennt man Deadlock. WS 2009/10

19 Softwarelösungen: Zwischenergebnis
Anforderung zu früh Deadlock (Versuch 3) Anforderung zu spät kein wechselseitiger Ausschluss, “kritischer Wettlauf” (Versuch 2) WS 2009/10

20 Softwarelösungen: Versuch 4
„Nichtstun“ in Schleife wird ersetzt durch zeitweilige Zurücknahme der Anforderung, um es anderen Prozessen zu erlauben, die Ressource zu belegen: /* Prozess 0 */ wiederhole { flag[0] := true; solange (flag[1] = true) flag[0] := false; /* zufäll. Verzög. */; } /* kritischer Abschnitt */ /* nichtkrit. Abschnitt */ /* Prozess 1 */ wiederhole { flag[1] := true; solange (flag[0] = true) flag[1] := false; /* zufäll. Verzög. */; } /* kritischer Abschnitt */ /* nichtkrit. Abschnitt */ WS 2009/10

21 Softwarelösungen: Versuch 4
Vorteil: Auch nicht-alternierender Zugriff auf kritischen Abschnitt. Wegen zufälliger Verzögerung nur geringe Wahrscheinlichkeit für Deadlock. Nachteil: „Busy waiting“ Deadlock nach wie vor möglich! Unsaubere Lösung! Verhalten ist schlecht vorhersagbar. Es gibt Situationen, in denen es nie voran geht es für sehr lange Zeit nicht voran geht. Nach Beobachtung eines unerwünschten Verhaltens tritt dieses möglicherweise über sehr lange Zeit nicht mehr auf -> kritische Wettläufe! WS 2009/10

22 Softwarelösungen: Versuch 5
3 gemeinsame Variablen: turn, flag[0], flag[1] Initialisierung: flag[0] := false; flag[1] := false; turn beliebig Variable turn bestimmt, welcher Prozess auf seiner Anforderung bestehen darf. /* Prozess 0 */ wiederhole { flag[0] := true; turn := 1; solange (flag[1] = true und turn = 1) tue nichts; /* kritischer Abschnitt */ flag[0] := false; /* nichtkrit. Abschnitt */ } /* Prozess 1 */ wiederhole { flag[1] := true; turn := 0; solange (flag[0] = true und turn = 0) tue nichts; /* kritischer Abschnitt */ flag[1] := false; /* nichtkrit. Abschnitt */ } WS 2009/10

23 Softwarelösungen: Versuch 5
Deadlock Kein Deadlock möglich wegen Variable turn! turn kann nicht gleichzeitig 0 und 1 sein. Wechselseitiger Ausschluss Sei o.B.d.A. Prozess 1 im kritischen Abschnitt zum Zeitpunkt t0 und Prozess 0 verlässt die “solange”-Schleife und geht auch in den kritischen Abschnitt. 2 Fälle: turn = 0 flag[1] = false Nicht-alternierender Zugriff Möglich, weil flag[i] = false, wenn Prozess i in nicht-kritischem Abschnitt. WS 2009/10

24 Softwarelösungen: Versuch 5
Beweis: Wechselseitiger Ausschluss Fall 1: turn = 0 (zum Zeitpunkt t0) t1: Zeitpunkt, an dem P1 zum letzten Mal „solange“-Schleife verlassen hat. t2: P1 führt zum letzten Mal turn = 0 aus. t3: P1 führt zum letzten Mal flag[1] = true aus. t2': P0 führt zum letzten Mal turn = 1 aus. t3': P0 führt zum letzten Mal flag[0] = true aus. Es gilt t2' < t2 da sonst turn = 0 zum Zeitpunkt t0 und t3' < t2'. Damit: t3' < t2' < t2 < t1 turn = 1 (P0) turn = 0 (P1) P0 geht in k.A. t3‘ t2‘ t2 t1 t0 P1 in k.A. WS 2009/10

25 Softwarelösungen: Versuch 5
Beweis (Fortsetzung Fall1): nach t3' kommt keine Anweisung mehr an flag[0] und nach t2 kommt keine Anweisung mehr an turn Somit: Zum Zeitpunkt t1 ist flag[0] = true und turn = 0. Damit ist zum Zeitpunkt t1 aber die „solange“-Schleife in P1 nicht verlassen worden. Widerspruch! turn = 1 (P0) turn = 0 (P1) P0 geht in k.A. t3‘ t2‘ t2 t1 t0 P1 in k.A. WS 2009/10

26 Softwarelösungen: Versuch 5
Beweis (Fortsetzung): Fall 2: flag[1] = false Wann kann flag[1] = false gesetzt werden ? nur an der Stelle (*) in P1 (und bei der Initialisierung)! /* Prozess 0 */ wiederhole { flag[0] := true; turn := 1; solange (flag[1] = true und turn = 1) tue nichts; /* kritischer Abschnitt */ flag[0] := false; /* nichtkrit. Abschnitt */ } /* Prozess 1 */ wiederhole { flag[1] := true; turn := 0; solange (flag[0] = true und turn = 0) tue nichts; /* kritischer Abschnitt */ flag[1] := false; (*) /* nichtkrit. Abschnitt */ } WS 2009/10

27 Softwarelösungen: Versuch 5
Beweis (Fortsetzung Fall 2: flag[1] = false) t1: Zeitpunkt, an dem P1 zum letzten Mal „solange“-Schleife verlassen hat. t2: P1 führt zum letzten Mal turn = 0 aus. t3: P1 führt zum letzten Mal flag[1] = true aus. D.h. flag[1] = false vor Zeitpunkt t3. Dann wird aber flag[1] = true. Da aber nach Annahme P1 im kritischen Abschnitt, muss flag[1] = true zum Zeitpunkt t0 weiterhin gelten. Widerspruch! flag[1] = false flag[1] = true P0 geht in k.A. t3 t2 t1 t0 P1 in k.A. WS 2009/10

28 Softwarelösungen: Versuch 5
Wechselseitiger Ausschluss Sei o.B.d.A. Prozess 1 im kritischen Abschnitt zum Zeitpunkt t0 und Prozess 0 verlässt die “solange”-Schleife und geht auch in den kritischen Abschnitt. 2 Fälle: turn = 0 flag[1] = false Für beide Fälle wurde gezeigt: Es kann nicht sein, dass P0 in den kritischen Abschnitt geht, wenn P1 bereits drin ist. Aus Symmetriegründen folgt: P0 und P1 sind nie gleichzeitig im kritischen Abschnitt. WS 2009/10

29 Softwarelösungen: Versuch 5
Vorteile: Nicht-alternierender Zugriff auf den kritischen Abschnitt Wechselseitiger Ausschluss garantiert Kein Deadlock Nachteil: Aktives Warten! Versuch 5 entspricht Petersons Algorithmus für wechselseitigen Ausschluss (1981). Verallgemeinerbar auf n Prozesse (wesentlich komplizierter!). WS 2009/10

30 Softwarelösungen: Zusammenfassung
Wechselseitiger Ausschluss ist in Software schwer zu realisieren. Alles was einfacher ist als Petersons Algorithmus ist höchstwahrscheinlich falsch. Beweise des Gegenteils sind durchaus willkommen … Fehler durch kritische Wettläufe, subtile Fehler Formale Beweise sind unabdingbar! Software-Lösungen für wechselseitigen Ausschluss benötigen aktives Warten. Effizientere Lösungen sind möglich durch Hardware-Unterstützung Ins Betriebssystem integrierte Lösungen. WS 2009/10


Herunterladen ppt "Kapitel 6 Nebenläufigkeit und wechselseitiger Ausschluss"

Ähnliche Präsentationen


Google-Anzeigen