next up previous contents
Next: Prozesssynchronisation in Java Up: Prozesssynchronisation Previous: Kritische Regionen   Contents


Monitore

Ein Monitor ist ebenfalls ein Konstrukt einer höheren Programmiersprache. In einem Monitor werden mehrere Prozeduren und Variablen zusammengefasst. Die Idee ist nun, dass in jedem Monitor eines Programms sich gleichzeitig immer nur ein Prozess befinden darf. Falls ein weiterer Prozess in den Monitor eintreten will, muss er sich schlafen legen und warten bis der andere Prozess den Monitor verlassen hat. Auf Variablen, die in einem Monitor deklariert sind, dürfen immer nur Prozeduren des gleichen Monitors zugreifen.

Dieses Konzept stellt sicher, dass sich immer nur ein Prozess innerhalb eines Monitors befindet. Für die Programmierung ist das aber nicht ausreichend. Es sollte zusätzlich durch Befehle möglich sein, Prozesse zu blockieren und wieder aufzuwecken. Dazu führt man einen neuen Typ von Variablen ein: condition. Es gibt zwei Operationen wait und signal, die auf Variablen vom Typ condition anwendbar sind. Die Operation wait blockiert einen Prozess bezüglich einer condition-Variablen. signal weckt einen beliebigen Prozess bezüglich einer condition-Variablen wieder auf. Nehmen wir nun an ein Prozess $P$ weckt einen Prozess $Q$ auf. In dieser Situation gibt es mehrere Möglichkeiten, die eintreten können:

  1. $P$ wartet bis $Q$ den Monitor verlässt oder blockiert wird.
  2. $Q$ wartet bis $P$ den Monitor verlässt oder blockiert wird.

In der Praxis gibt es verschiedene Implementierungen. Wir werden später eine Implementierung für Fall 1 angeben. In der existierenden Programmiersprache Concurrent Pascal sind Monitore aber beispielsweise so realisiert, dass $P$ sofort den Monitor verlässt, wenn $Q$ aufgeweckt wurde. Das bedeutet allerdings, dass jeder Prozess innerhalb eines Monitors nur ein signal senden kann.

Betrachten wir nun einen Lösungsansatz für das Erzeuger-Verbraucher-Problem mit einem Monitor (Abbildung [*]).

Figure: Lösung des Erzeuger-Verbraucher-Problem mit einem Monitor
\begin{figure}\begin{center}
\begin{program}
monitor ProducerConsumer
var ful...
...consume_item(item);
end; (* consumer *)
\end{program} \end{center}\end{figure}

Wir müssen zwei neue Prozeduren enter und remove einführen, die beide in dem gleichen Monitor implementiert sind.

Abschließend geben wir noch eine mögliche Übersetzung von Monitoren an. Für jeden Monitor führen wir einen Semaphor mutex ein (initialisiert mit 1). Beim Eintreten in dem Monitor muss downmutex ausgeführt werden. Zusätzlich wird noch ein Semaphor next und eine Integer-Variable next-count eingeführt, welche die Prozesse zählt, die auf den Eintritt in den Monitor warten. Jede Prozedur $F$ eines Monitors wird dann übersetzt nach:


\begin{program}
down(mutex);
\textrm{Rumpf von \(F\)};
if next-count > 0
up(next);
else
up(mutex);
\end{program}


Für jede condition-Variable x wird ein Semaphor x-sem und eine Integer-Variable x-count eingeführt (beide mit 0 initialisiert). Die Operation wait(x) wird dann wie folgt implementiert:


\begin{program}
x-count = x-count + 1;
if next-count > 0
up(next);
else
up(mutex);
down(x-sem);
x-count = x-count - 1;
\end{program}


Bleibt noch die Übersetzung der Operation signal(x):


\begin{program}
if x-count > 0
\{
next-count = next-count + 1;
up(x-sem);
down(next)
next-count = next-count - 1;
\}
\end{program}


next up previous contents
Next: Prozesssynchronisation in Java Up: Prozesssynchronisation Previous: Kritische Regionen   Contents
Prof. Dr. Pluemicke 2003-05-10