Systeme 1 Kapitel 7.2 Dining philosophers problem WS 2009/101.

13
Systeme 1 Kapitel 7.2 Dining philosophers problem WS 2009/10 1

Transcript of Systeme 1 Kapitel 7.2 Dining philosophers problem WS 2009/101.

Page 1: Systeme 1 Kapitel 7.2 Dining philosophers problem WS 2009/101.

Systeme 1

Kapitel 7.2Dining philosophers problem

WS 2009/10 1

Page 2: Systeme 1 Kapitel 7.2 Dining philosophers problem WS 2009/101.

Dining philosophers problem

• Fünf Philosophen sitzen an einem runden Tisch.• Vor jedem Philosophen steht ein Teller mit Spaghetti.• Die Spaghetti sind so fettig, dass zwei Gabeln zum

Essen benötigt werden.• Zwischen den Tellern liegt

jeweils eine Gabel.

• (Dijkstra 1965)

WS 2009/10 2

Page 3: Systeme 1 Kapitel 7.2 Dining philosophers problem WS 2009/101.

Dining philosophers problem

• Ablauf:– Die Philosophen sitzen am Tisch und diskutieren über

philosophische Probleme.– Wird ein Philosoph hungrig, so versucht er die rechte und

die linke Gabel zu bekommen. – Wenn es ihm gelingt beide Gabeln

zu bekommen, isst er eine Zeit lang, legt die Gabeln wieder zurück und wendet sich wieder der Diskussion zu.

WS 2009/10 3

Page 4: Systeme 1 Kapitel 7.2 Dining philosophers problem WS 2009/101.

Dining philosophers problem

• Angenommen alle fünf Philosophen nehmen ihre linke Gabel gleichzeitig. Dann kann keiner seine rechte Gabel aufnehmen und wartet.

DeadlockWS 2009/10 4

/* Philosoph(i) (i=1...N, N=5 */

philosopher(i){ philosophise(); take_fork(i); /* nimm linke Gabel */ take_fork((i + 1) % N); /* nimm Rechte Gabel (modulo N)*/ eat(); put_fork(i); put_fork((i + 1) % N);}

/* take_fork(i) Nimm Gabel i */

take_fork(i){ solange ( Gabel(i) belegt ) warte;

Gabel(i); /* Gabel i ist belegt */}

Page 5: Systeme 1 Kapitel 7.2 Dining philosophers problem WS 2009/101.

Dining philosophers problem• Verbesserung:

Wenn rechte Gabel belegt, dann lege linke Gabel wieder zurück.

WS 2009/10 5

/* Philosoph(i) (i=1...N, N=5 */

philosopher(i){ philosophise(); take_fork(i); /* nimm linke Gabel */ take_fork((i + 1) % N); /* nimm rechte Gabel (modulo N) Wenn Gabel (i + 1) % N belegt lege Gabel (i) zurück und versuche es später erneut */ ...

Angenommen alle fünf Philosophen nehmen ihre linke Gabel gleichzeitig. Dann ist die jeweils rechte Gabel belegt und sie legen die linke wieder zurück. Im nächsten Versuch greifen wieder alle gleichzeitig zur linken Gabel usw...

Die Prozesse laufen zwar alle uneingeschränkt weiter, aber sie machen keine Fortschritte Sie verhungern.

Page 6: Systeme 1 Kapitel 7.2 Dining philosophers problem WS 2009/101.

Dining philosophers problem• Verbesserung– Jeder Philosoph wartet einen zufälligen Zeitraum bis

zum nächsten Versuch.– Dann ist die Wahrscheinlichkeit sehr gering, dass es

zum Aushungern kommt.– Aber unsaubere Lösung. In bestimmten Bereichen

(Kraftwerk, Raumsonde, etc...) sollen selbst unwahrscheinliche Ereignisse soweit wie möglich ausgeschlossen werden.• Murphys Law: „If there's more than one possible outcome of

a job or task, and one of those outcomes will result in disaster or an undesirable consequence, then somebody will do it that way."

WS 2009/10 6

Page 7: Systeme 1 Kapitel 7.2 Dining philosophers problem WS 2009/101.

Dining philosophers problem

• Verbesserungsvorschlag:– Führe binären Semaphor ein:

WS 2009/10 7

/* globaler semaphor initialisiert mit 1 */Semaphor binSem = 1;

/* Philosoph(i) (i=1...N, N=5 */philosopher(i){ philosophise(); down(binSem); take_fork(i); take_fork((i + 1) % N); eat(); put_fork(i); put_fork((i + 1) % N); up(binSem);}

Theoretisch korrekte Lösung. Aber es kann immer nur ein Philosoph essen. Mit fünf Gabeln können aber zwei Philosophen gleichzeitig essen.

Keine performante Lösung!

Page 8: Systeme 1 Kapitel 7.2 Dining philosophers problem WS 2009/101.

Dining philosophers problem

• Vorschlag von Tanenbaum:– Diese Lösung verwendet ein globales Feld (status) (Array), um zu

verfolgen, in welchem Zustand sich ein Philosoph aktuell befindet.– Ein hungriger Philosoph kann nur in den essenden Zustand

übergehen, wenn seine beiden Nachbarn nicht am Essen sind.– Das Programm verwendet für jeden Philosophen einen Semaphor, so

dass diese blockieren können, falls die Gabeln in Gebrauch sind.

WS 2009/10 8

/* global verfügbare Variablen */

Integer N = 5; /* Anzahl der Philosophen */Semaphor binSem = 1; /* einfache binäre Semaphore */Semaphor philSem[N]; /* ein Semaphor pro Philosoph */String status[N]; /* Zustand der einzelnen Philosophen */

/* Hilfsfuntionen */left(i) { return (i+N-1)%N; } /* Index linker Nachbar */right(i) { return (i+1)%N; } /* Index rechter Nachbar */

Page 9: Systeme 1 Kapitel 7.2 Dining philosophers problem WS 2009/101.

Dining philosophers problem

• Vorschlag von Tanenbaum:

WS 2009/10 9

/* Funktion zum Testen der Nachbarn */

test(i) /* Test für Philosoph i (i = 0 ... N-1){ wenn( status[i] == “hungrig“ und status[left(i)] != “essend“ und status[right(i)] != “essend“ ) {

/* linker und rechter Nachbar essen nicht und Philosoph ist hungrig, dann darf der Philosoph i essen. */

up(philSem[i]); /* löst evtl. wartenden Philosophen */ }}

Page 10: Systeme 1 Kapitel 7.2 Dining philosophers problem WS 2009/101.

Dining philosophers problem

• Vorschlag von Tanenbaum:

WS 2009/10 10

/* Nehme Gabeln */

take_forks(i) /* Für Philosoph i (i = 0 ... N-1){ down(binSem); /* betrete kritischen Abschnitt */ status[i] = „hungrig“; /* setze Status auf hungrig */ test(i); /* versuche beide Gabeln zu bekommen */ up(binSem); down(philSem[i]); /* blockiere wenn Gabeln nicht erhalten */ }

Bemerkung:Die binäre Semaphore schützt den Zugriff auf das gemeinsam genutzte Statusfeld.

Der Aufruf down(philSem[i]) blockiert den Philosophen, falls test(i) den Semaphoren vorher nicht erhöht hatte. up() wurde in test(i) nur ausgeführt, falls die beiden Gabeln verfügbar waren.

Page 11: Systeme 1 Kapitel 7.2 Dining philosophers problem WS 2009/101.

Dining philosophers problem

• Vorschlag von Tanenbaum:

WS 2009/10 11

/* Lege Gabeln zurück */

put_forks(i) /* Für Philosoph i (i = 0 ... N-1){ down(binSem); /* betrete kritischen Abschnitt */ status[i] = „denkend“; /* setze Status auf denkend */

/* können die beiden Nachbarn essen ? */ test(left(i)); test(right(i));

up(binSem);}

Page 12: Systeme 1 Kapitel 7.2 Dining philosophers problem WS 2009/101.

Dining philosophers problem

• Vorschlag von Tanenbaum:

WS 2009/10 12

/* Thread Funktionen *//* Parallel für alle Philosophen */

philosopher(i) /* Für Philosoph i (i = 0 ... N-1){ loop { philosophise(); take_forks(i); eat(); put_forks(i); }}

Bemerkung:Auch diese Lösung hat ein Problem. Unter bestimmten Umständen kann es vorkommen, dass ein Philosoph verhungert. Übung

Page 13: Systeme 1 Kapitel 7.2 Dining philosophers problem WS 2009/101.

Dining philosophers problem• Um ein Verhungern zu verhindern, benötigt man

zusätzlich ein Priorisierungssystem, um blockierte Philosophen in der Reihenfolge zu wecken, in der sie blockiert wurden:– Beispiel 1:

• Wenn ein Philosoph hungrig ist, muss er erst eine Nummer ziehen.

• Er darf erst dann essen, wenn er die niedrigste Nummer hat.– Beispiel 2: Priorisierung in der Tanenbaum-Lösung

• Philosoph i darf nur dann essen, wenn keiner seiner Nachbarn nicht schon „sehr lange“ wartet.

Scheldulingalgorithmus

WS 2009/10 13