Documents
Resources
Learning Center
Upload
Plans & pricing Sign in
Sign Out
Your Federal Quarterly Tax Payments are due April 15th Get Help Now >>

Approximate Symbolic Model Checking for Incomplete Designs_1_

VIEWS: 23 PAGES: 23

									                        Kapitel 10
                    Nebenläufigkeit und
                 wechselseitiger Ausschluss




RW-Systemarchitektur        Kap. 10
                                              1
                  Überblick Betriebssysteme
6 Einführung
7 Prozesse, Fäden (threads), Scheduling
8. Speicherverwaltung
9 Dateisysteme
10 Nebenläufigkeit und wechselseitiger Ausschluss
    10.1 Softwarelösungen für wechselseitigen Ausschluss
    10.2 Wechselseitiger Ausschluss in Hardware
    10.3 Wechselseitiger Ausschluss ins Betriebssystem integriert
11 Deadlocks
12 historisches
13 aktuelle Forschung




RW-Systemarchitektur           Kap. 10
                                                                    2
                           Nebenläufigkeit

•   Größere Softwaresysteme sind häufig realisiert als eine Menge von
    nebenläufigen Prozessen.
•   Nebenläufigkeit = „potentieller Parallelismus“
     – Nebenläufige Prozesses 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 exklusiver Zugriff
    durch wechselseitiger Ausschluss garantiert werden!
• Hier:
     – Softwarelösungen
     – Hardware-Lösungen
     – Integration ins Betriebssystem

RW-Systemarchitektur                   Kap. 10
                                                                                       3
                          Ein einfaches Beispiel
   void echo()
   {
      chin = getchar();
                  /* Zeichen einlesen, speichern in Variable chin */
      putchar (chin);
                  /* Zeichen ausgeben */
   }

Annahme: 2 Threads führen (u.a.) diesen Code aus.
                                                             Problem: Semantik
• Threads haben einen gemeinsamen Adressraum.
   ) Variable chin ist eine gemeinsame Ressource!            verändert sich mit dem
Mögliche Ausführungsreihenfolge:                             Thread-Schedule!
    – Thread 1 liest Zeichen, wird unterbrochen ) Thread 2
    – Thread 2 führt Prozedur komplett aus.
    – Thread 1 führt Rest der Prozedur aus.                  Unterbrechung hat
                                                             Effekt auf gemeinsame
                                                             Variable.

   RW-Systemarchitektur                  Kap. 10
                                                                                      4
           Produzenten-Konsumenten-Problem
• Paradigma für kooperierende
  Prozesse:                             Gemeinsamer Puffer
• Prozess producer produziert           #define BUFFER_SIZE 10
  Information, welche von einem         typedef struct {
  Prozess consumer konsumiert wird.         ...
• Zwischen producer und consumer        } item;
  gibt es einen zyklischen Puffer       item buffer[BUFFER_SIZE];
  buffer fester Größe.                  int in = 0;
                                        int out = 0;




   RW-Systemarchitektur       Kap. 10
                                                                    5
   Beschränkter Puffer – Insert() und Remove()
                  in                    out

                                                             buffer

 producer                                consumer
while (true) {                          while (true) {
       /* Produziere ein Element           while (in == out)
   */                                        ; /* tue nichts – nichts
   while (((in = (in + 1) %                im Puffer */
   BUFFER_SIZE) == out)
         ;   /* do nothing -- no                 /* entferne ein Element
   free buffers */                            aus Puffer */
   buffer[in] = item;                              item = buffer[out];
   in = (in + 1) % BUFFER SIZE;                    out = (out + 1) %
      }                                       BUFFER SIZE;
                                              return item;
  RW-Systemarchitektur        Kap. 10
                                                }                       6
   Produzent-Konsument mit beschränktem
         Puffer – Was geht schief?
• Geschwindigkeit Produzent > Geschwindigkeit Konsument 
  Pufferinhalte werden überschrieben.
• Geschwindigkeit Produzent < Geschwindigkeit Konsument 
  Konsument liest leere Pufferfelder
• Korrektheit hängt von der relativen Geschwindigkeit der
  beiden Threads zueinander ab – nur korrekt bei gleicher
  Geschwindigkeit und „günstiger Initialisierung“.




RW-Systemarchitektur      Kap. 10
                                                            7
                        Nebenläufigkeit
• Grundlegende Fragen bei Nebenläufigkeit:
   – Betriebssystem muss Ressourcen der aktiven Prozesse verwalten.
   – Es 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.
• 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 (Prozess nicht blockiert, macht aber keinen
     Fortschritt).

 RW-Systemarchitektur             Kap. 10
                                                                           9
                    Anforderungen an
                wechselseitigen Ausschluss

1. Höchstens ein Prozess im kritischen Abschnitt.
2. Jeder Prozess hält sich nur endliche Zeit im kritischen
   Abschnitt auf.
3. Wenn ein Prozess in den kritischen Abschnitt will, so muss er
   nur endliche Zeit darauf warten.
4. Wenn kein Prozess im kritischen Abschnitt ist, so wird ein
   interessierter Prozess ohne Verzögerung akzeptiert.
5. Alles funktioniert unabhängig von der relativen
   Ausführungsgeschwindigkeit der Prozesse.



RW-Systemarchitektur         Kap. 10
                                                                   10
                 10.1 Softwarelösungen für
                wechselseitigen Ausschluss

• Hier:
     – 5 verschiedene Lösungsversuche für wechselseitigen
       Ausschluss
     – Analyse der einzelnen Lösungen


• Letzter Versuch entspricht der Lösung von Peterson (1981)
• Lösung von Peterson ist eine Vereinfachung des Algorithmus
  von Dekker (Anfang der 60er Jahre).




RW-Systemarchitektur           Kap. 10
                                                               11
                            Versuch 1
• Voraussetzung:
    – 2 Prozesse konkurrieren um eine Ressource
    – Gemeinsame Variable turn besagt, wer dran ist.
    – turn ist mit beliebigem Wert initialisiert.


/* Prozess 0 */                       /* Prozess 1 */
repeat                                repeat
  {                                     {
    while (turn  0)                      while (turn  1)
      tue nichts;                           tue nichts;
    /* kritischer Abschnitt */            /* kritischer Abschnitt */
    turn := 1;                            turn := 0;
    /* nichtkrit. Abschnitt */            /* nichtkrit. Abschnitt */
  }                                     }


  RW-Systemarchitektur           Kap. 10
                                                                   12
                       Versuch 1: Analyse
• Vorteil:
     – Wechselseitiger Ausschluss ist garantiert.
• Nachteil:
     – „Busy waiting“ = aktives Warten
       („while (turn  0) tue nichts;”)
       ) Verschwendung von Rechenzeit beim Warten
     – Nur abwechselnder Zugriff auf kritischen Abschnitt

• Beispiel für kritische Situation:
     – Prozess 0 ist schnell, Prozess 1 ist langsam (sehr langer nicht-
       kritischer Abschnitt)
     – …
     – Bedingung 4 ist nicht erfüllt!


RW-Systemarchitektur              Kap. 10
                                                                          13
                         Versuch 2
• Jetzt 2 gemeinsame Variablen zur Kommunikation:
    – Prozess 0 schreibt auf ready[0], liest beide
    – Prozess 1 schreibt auf ready[1], liest beide
    – Bedeutung von ready[i] = true:
      Prozess i will in den kritischen Abschnitt
    – Initialisierung: ready[0] := false; ready[1] := false;

/* Prozess 0 */                    /* Prozess 1 */
repeat                             repeat
  {                                  {
    while (ready[1] = true)            while (ready[0] = true)
       tue nichts;                        tue nichts;
    ready[0] := true;                  ready[1] := true;
    /* kritischer Abschnitt */         /* kritischer Abschnitt */
    ready[0] := false;                 ready[1] := false;
    /* nichtkrit. Abschnitt */         /* nichtkrit. Abschnitt */
  }                                  }
  RW-Systemarchitektur        Kap. 10
                                                                14
                         Versuch 2: Analyse
• Vorteil: Auch nicht-alternierender Zugriff auf kritischen Abschnitt
• Nachteile:
   – „Busy waiting“ („while (ready[i]  true) tue nichts;”)
   – Wechselseitiger Ausschluss nicht garantiert!!
• Beispiel für Fehlersituation :
   – ready[0] = ready[1] = false
   – Prozess 0 schließt Schleife („while (ready[1]  true) tue
     nichts;”) ab, gibt CPU ab
   – Prozess 1 schließt Schleife („while (ready[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



 RW-Systemarchitektur                    Kap. 10
                                                                                  15
                         Versuch 3
  • Anforderung des kritischen Abschnittes wird vorgezogen, um
    das gezeigte Problem zu verhindern:



/* Prozess 0 */                    /* Prozess 1 */
repeat                             repeat
  {                                  {
    ready[0] := true;                  ready[1] := true;
    while (ready[1] = true)            while (ready[0] = true)
       tue nichts;                        tue nichts;
    /* kritischer Abschnitt */         /* kritischer Abschnitt */
    ready[0] := false;                 ready[1] := false;
    /* nichtkrit. Abschnitt */         /* nichtkrit. Abschnitt */
  }                                  }

  RW-Systemarchitektur        Kap. 10
                                                                 16
                        Versuch 3: Analyse
• Vorteil:
   – Auch nicht-alternierender Zugriff auf kritischen Abschnitt
   – Wechselseitiger Ausschluss garantiert!
• Nachteil:
   – „Busy waiting“ („while (ready[i]  true) tue nichts;”)


• Es kann aber trotzdem ein Problem auftreten:
   –   ready[0] = ready[1] = false
   –   Prozess 0 setzt ready[0] := true und gibt CPU ab
   –   Prozess 1 setzt ready[1] := true
   –   Jetzt werden beide Prozesse ihre Schleife
       „while (ready[i]  true) tue nichts;” nie verlassen!

   – Eine solche Situation nennt man Livelock.
 RW-Systemarchitektur             Kap. 10
                                                                  17
                Wechselseitiger Ausschluss



…
• Ergebnis:
     – Anforderung zu früh
       ) Livelock
     – Anforderung zu spät
       ) kein wechselseitiger Ausschluss, “kritischer Wettlauf” (race
       condition)




RW-Systemarchitektur             Kap. 10
                                                                        18
                         4. Versuch
  • „Nichtstun“ in Schleife wird ersetzt durch zeitweilige
    Zurücknahme der Anforderung, um es anderen Prozessen zu
    erlauben, die Ressource zu belegen:

/* Prozess 0 */                   /* Prozess 1 */
repeat                            repeat
  {                                 {
    ready[0] := true;                 ready[1] := true;
    while (ready[1] = true)           while (ready[0] = true)
       {                                 {
         ready[0] := false;                ready[1] := false;
         /* zufäll.Verzög. */;             /* zufäll.Verzög. */;
         ready[0] := true;                 ready[1] := true;
       }                                 }
    /* kritischer Abschnitt */        /* kritischer Abschnitt */
    ready[0] := false;                ready[1] := false;
    /* nichtkrit. Abschnitt */        /* nichtkrit. Abschnitt */
  }                                 }
  RW-Systemarchitektur       Kap. 10
                                                               19
                        Versuch 4: Analyse
• 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 oder
        • 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 (race condition)!
 RW-Systemarchitektur                 Kap. 10
                                                                       20
                         Versuch 5
• 3 gemeinsame Variablen: turn, ready[0], ready[1]
• Initialisierung: ready[0] := false; ready[1] := false;
  turn beliebig
• Variable turn bestimmt, welcher Prozess dran ist.

/* Prozess 0 */                  /* Prozess 1 */
repeat                           repeat
  { ready[0] := true;              { ready[1] := true;
    turn := 1;                       turn := 0;
    while (ready[1] = true &&        while (ready[0] = true &&
        turn = 1)                        turn = 0)
       tue nichts;                      tue nichts;
    /* kritischer Abschnitt */       /* kritischer Abschnitt */
    ready[0] := false;               ready[1] := false;
    /* nichtkrit. Abschnitt */       /* nichtkrit. Abschnitt */
  }                                }

  RW-Systemarchitektur       Kap. 10
                                                                  21
                          5. Versuch: Analyse (1)
• Deadlock:
   – Kein Deadlock möglich wegen Variable turn!
   – turn kann nicht gleichzeitig 0 und 1 sein.
• Wechselseitiger Ausschluss:
   – Nur einer von beiden interessiert: der andere darf eintreten,
   – Beide interessiert: der darf eintreten, auf den turn zeigt
• Nicht-alternierender Zugriff:
   – Möglich, weil ready[i] = false, wenn Prozess i in nicht-kritischem
     Abschnitt.




   RW-Systemarchitektur             Kap. 10
                                                                          22
                       5. Versuch: Analyse (2)

• 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!).

RW-Systemarchitektur              Kap. 10
                                                                   23
   Wechselseitiger Ausschluss in Software –
       Was haben wir bisher gelernt?
• 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


RW-Systemarchitektur               Kap. 10
                                                                      24

								
To top