next up previous contents
Next: Aufgabe Up: Prozesssynchronisation Previous: Monitore   Contents

Prozesssynchronisation in Java

In Java gibt es ebenfalls die Möglichkeit durch wechselseitigen Ausschluss auf kritische Bereiche zuzugreifen. Neben der Peterson Lösung (Abschnitt [*]) bietet Java die Möglichkeit kritische Bereiche als Methoden durch das Schlüsselwort synchronized zu realisieren.

In Java besitzt jedes Objekt genau ein Lock5.4. Wenn ein Objekt referenziert wird (Zugriff auf das Objekt selbst, ein Attribut oder eine Methode des Objekts), wird der Lock üblicherweise ignoriert. Nur wenn die Methode auf die zugegriffen wird durch synchronized ausgezeichnet ist, wird der Lock betrachtet. Ist in diesem Fall der Lock von einem anderen Thread bereits gesetzt worden, so wird der aktuelle Thread blockiert und in eine Menge von wartenden Threads eingetragen. Wenn der Lock nicht gesetzt ist, so setzt der aktuelle Thread den Lock und arbeitet die synchronized Methode ab. Beim Verlassen der Methode wird der Lock wieder aufgehoben. Wenn nun die Menge der wartenden Threads nicht leer ist, so wird ein zufälliger Thread bestimmt, der dann den Lock setzt und in den rechenbereiten Zustand überführt wird.

Betrachten wir im Folgenden das Erzeuger-Verbraucher-Problem implementiert in Java.

Zunächst die Klasse BoundedBuffer, die den Speicher (Buffer) mit ihren Methoden enter_item und remove_item (Abbildung [*]).

Figure: Bounded Buffer
\begin{figure}\begin{center}
\begin{verbatim}public class Consumer extends Thr...
...n(''Removed: '' + n.getString());
}
}
}\end{verbatim} \end{center}\end{figure}

In den Methoden enter_item und remove_item werden, wenn der Speicher voll bzw. leer ist jeweils die Methode wait aufgerufen. Die Methode wait ist eine Methode der Klasse Object. Sie hat die Eigenschaften:
  1. Der derzeitige Lock wird aufgehoben.
  2. Der Thread wird in den blockierten Zustand überführt.
  3. Der Thread wird in die Menge der wartenden Threads bezüglich des waits eingefügt5.5.

Am Ende der beiden Methoden wird jeweils die Methode notify aufgerufen. Auch diese Methode hat die Klasse BoundedBuffer von der Klasse Object geerbt. Die Methode notify hat folgende Eigenschaften:

  1. Es wird zufällig ein Prozess aus der Menge der bezüglich wait in diesem Objekt blockiert wurden ausgewählt.
  2. Er wird in in die Menge der auf einen Lock wartenden Threads eingefügt.

Die Klasse Producer (Abbildung [*]) ist für die Produktion der Speichereinträge verantwortlich.

Figure: Producer
\begin{figure}\begin{center}
\begin{verbatim}public class Producer extends Thr...
...tered: '' + n.getString());
i++;
}
}
}\end{verbatim} \end{center}\end{figure}

Es werden Objekte der Klasse NewItem in Abhängigkeit einer int-Variablen angelegt. Diese werden dann durch den Aufruf der Methode enter_item in den Speicher eingetragen.

Die Klasse Consumer (Abbildung [*]) ist das Gegenstück zu Consumer und funktioniert analog.

Figure: Consumer
\begin{figure}\begin{center}
\begin{verbatim}public class Consumer extends Thr...
...n(''Removed: '' + n.getString());
}
}
}\end{verbatim} \end{center}\end{figure}

Bleibt noch eine Klasse, die die Erzeuger-Verbraucher-Implementierung steuert: BufferServer (Abbildung [*]).

Figure: Steuert die Erzeuger-Verbraucher-Implementierung
\begin{figure}\begin{center}
\begin{verbatim}public class BufferServer {
publ...
...start();
consumerThread.start();
}
}\end{verbatim}\par\end{center}\end{figure}

Es werden jeweils die Threads Producer und Consumer gestartet.



Subsections
next up previous contents
Next: Aufgabe Up: Prozesssynchronisation Previous: Monitore   Contents
Prof. Dr. Pluemicke 2003-05-10