30 - 10.2.6 Monitore: Beispiel Ringpuffer [ID:24408]
50 von 64 angezeigt

Gut, ich möchte jetzt abschließend ein kurzes Beispiel bringen von einem Datenringpuffer,

den wir jetzt mal so als Monitor formuliert sehen wollen. Das ist ein Beispiel, was wir aus einer

früheren Lehrveranstaltung schon kennen, wo wir das schon eingeführt haben und dann ja auf der

C-Sprachen-Ebene geblieben sind. Hier wollen wir mal sozusagen eine fiktive Programmiersprache

annehmen, nämlich Concurrent C++. Diese Sprache gibt es nicht wirklich. Hier sehen wir eben, das

ist eine objektorientierte Sprache. Java ähnlich, wir haben ja Klassen, Class Buffer beschreibt

dann also praktisch den Blueprint unserer Pufferimplementierung als Ringpuffer ausgelegt. Wir

geben hier, machen aus einer Template-Klasse, was bedeutet, dass wir dann halt als zusätzlichen

Parameter spezifizieren, von welchem Typ denn die einzelnen Elemente, die in diesem Puffer

denn zum Beispiel drin sind, ist ein Parameter, der groß T-Parameter. Dann haben wir ein N-Parameter

mit einer Default-Belegung 64, wo wir dann damit zum Ausdruck bringen wollen, wie groß unser Puffer

überhaupt dimunziert ist. Oder dann haben wir hier noch so eine andere Spezifikation, da sagen wir

dann einfach, okay diese Template-Klasse soll ein Monitor sein. Es ist also eine synchronisierte

Klasse, wenn man so will nach dem Monitor-Prinzip. Dann haben wir hier noch Bedingungsvariablen,

die wir verwenden werden, um denn die eigentlichen Einfüge- und Austragoperationen, also Put und Get,

denn aufeinander abzustimmen, also koordinieren zu können. So wie wir das in der letzten

Vorlesungsstunde eben an dem ersten Beispiel schon mal so ein Stück weit betrachtet haben. Okay,

denn würde hier bedeuten der Atomic-Bereich, da beginnt es denn eigentlich mit den nach außen hin

exportierten Prozeduren, mit den Monitor-Prozeduren. Und da haben wir gesagt, okay die sind eben

implizit automat. Das sind also hier öffentliche Prozeduren. Da haben wir den Konstruktor, der also

erst mal diese in- und out-Variablen, die Indexvariablen halt vorinitialisiert mit einem

Wert Null. Und dann haben wir die eigentlichen Operationen Put und Get mit Put, um dann immer

nach und nach ein Element in diesen Puffer einzutragen oder mit Get eben das nächste Element

aus dem Puffer halt herauszunehmen. Und wir wissen eben, dass das Eintragen in dem Puffer so

geschehen muss. Also konsistent, das heißt, jetzt soll kein Element, kein ein Puffereintrag

überschrieben werden. Ist der Puffer voll, muss der Prozess warten. Ist der Puffer leer, muss der

Prozess auch warten. Die Wartebedingungen für einen vollen Puffer haben wir jetzt hier so formuliert.

In plus eins modulo n ist gleich out. Die beiden Indexwerte stimmen überein. Denn soll das die

Wartebedingungen für den Prozess sein, der eine Put-Operation ausführt. Kein freier Pufferplatz,

er würde dann mit der Bedingungsvariablen Free arbeiten und darauf eine Wait-Operation ausführen.

Das heißt, er würde jetzt hier blockieren und so lange warten, bis eine Signalisierung zu diesem

Free halt geschieht. Diese Signalisierung kommt hier unten in der Zeile 19. Das heißt ja hier oben,

Zeile 11 von der Logik hier. Alle Puffereinträge sind belegt. Dann müssen wir mindestens eine

Get-Operation ausführen, dass ein Puffereintrag befreit wird. Also frei wird und das signalisieren

wir mit der Free-Operation. Vorher wird die Wartebedingungen für den Prozess, der hier oben

die Bedingungen formuliert hat, eben aufgehoben. Das ist dann entsprechend eigentlich genau diese

out plus plus Operation, die man hier unten im Get in der Zeile 18 durchführt. Wo wir nämlich

hier das nächste Element aus dem Puffer herauslesen und dann den Out-Index um eins erhöhen, letztendlich

entsprechend des Ring-Puffer-Konzepts. Nun bei der Get-Operation kann es eben auch eine Wartepedingung,

eine Wartesituation geben, in dem Fall, wo der Puffer nämlich leer ist. Da ist nichts drin und

ist genau dann der Fall, wie so ein Initialzustand hier in ist gleich out. Das wenn out gleich in

Index ist, da muss ein Prozess warten. Die inverse Operation dafür wäre denn die, dass

wenigstens ein, das erste Element in diesem Puffer eingetragen wird und das wird signalisiert mit der

Zeile 13, wo wir dann sagen Data-Signal. Da soll auf die Bedingungsvariable Data der nächste Prozess,

vielleicht auch alle Prozesse eben signalisiert werden, bereitgestellt werden, die möglicherweise

hier unten in der Get-Operation halt warten. Und wie gesagt, wartet hier kein Prozess,

dann geht das Signal verloren. Das gilt halt für diese Signaloperation in der Zeile 13,

denn wartet eben keiner im Get oder hier unten Zeile 19. Wenn hier keiner im Put wartet,

dann wird dieses Signal eben auch nicht gespeichert. Das ist das Grundprinzip. So einfach würde jetzt

unser bounded buffer halt aussehen können, wenn man so ein Monitorkonzept halt hat. Ein anderer

Teil eines Kapitels:
10.2 Monitore

Zugänglich über

Offener Zugang

Dauer

00:07:01 Min

Aufnahmedatum

2020-11-19

Hochgeladen am

2020-11-19 19:28:17

Sprache

de-DE

Einbetten
Wordpress FAU Plugin
iFrame
Teilen