Beim Programmieren verteilter Systeme müssen die sequenziellen und nebenläufigen Programmabarbeitungen für den Programmentwurf konzeptionell und für die Implementierung durch entsprechende Konstruktionen einer Programmiersprache beschrieben werden. Eine solche Beschreibung ist als eine Aufforderung an das jeweilige Programmiersystem zu verstehen, bestimmte Befehlsfolgen entweder zwingend sequenziell oder, falls dies möglich ist, nebenläufig abzuarbeiten. Es ist bereits im Abschnitt 1.2.1 (Zeitliche Beziehungen) darauf hingewiesen worden, dass es unschädlich ist, wenn Befehle, die nebenläufig durchgeführt werden dürfen, sequenziell abgearbeitet werden!
Konzeptionelle Überlegungen führen schnell zu grafischen Methoden. Die bekannteste davon sind die Petri-Netze, benannt nach dem deutschen Informatiker Carl Adam Petri (1926-2010). Eine Beschäftigung mit ihnen ist im Rahmen einer Einführungsveranstaltung zu zeitaufwändig und bleibt einer Vertiefungsveranstaltung vorbehalten.
Weit weniger aufwändig, allerdings auch weit weniger mächtig, sind die sogenannten Wartegraphen, die auch Präzedenz- oder Vorranggraphen genannt werden. Für die Belange der Lehrveranstaltung sind sie völlig ausreichend. Wartegraphen sind ein elementares Hilfsmittel für den Entwurf von Programmen und dürfen nicht mit Flussdiagrammen verwechselt werden. Sie beschreiben, bei welchen Teilen eines Programms mit der Abarbeitung gewartet werden muss, bis die Abarbeitung anderer Teile beendet ist.
In der grafischen Darstellung werden zeitliche Abläufe, wie sie beispielsweise bei einer Befehlsabarbeitung entstehen, als Kästchen dargestellt. Eine Sequenzialität A → B zweier zeitlicher Abläufe A und B wird dadurch ausgedrückt, dass die beiden zugehöhrigen Kästchen durch einen Pfeil miteinander verbunden werden, wobei die Pfeilspitze zu dem zeitlichen Ablauf zeigt, der nach dem anderen kommt. Bei einer Nebenläufigkeit zweier zeitlicher Abläufe C und D werden die beiden zugehörigen Kästchen nicht durch einen Pfeil miteinander verbunden. Das folgende Bild zeigt diese beiden Basiskonstruktionen:
Der Pfeil zwischen zwei Kästchen bringt anschaulich ein aufeinander Wartenmüssen zum Ausdruck: Der zeitliche Ablauf, auf den der Pfeil zeigt, darf erst dann beginnen, wenn der, von dem der Pfeil kommt, vollständig beendet ist. Grob formuliert, muss im obigen Bild B auf A warten. Als Beispiel soll ein Ausschnitt aus einem Java-Programm mit drei Befehlen angegeben werden. Die drei darin vorkommenden Variablen x, y und z seien vom Typ int und korrekt vereinbart worden. Die Befehlsfolge soll lauten:
Wird die Notation eines jeden dieser drei Befehle als der zeitliche Ablauf seiner Abarbeitung verstanden, dann gehört zu der Befehlsfolge folgender Wartegraph:
Er bringt zum Ausdruck, dass die ersten beiden Befehle nebenläufig durchgeführt werden dürfen, aber mit der Durchführung des dritten auf das Ende der beiden anderen gewartet werden muss.
Alle Programmiersprachen stellen eine Möglichkeit für die Darstellung sequenzieller Programmabarbeitungen zur Verfügung. Bei einigen Sprachen werden Programmbefehle, die sequenziell abgearbeitet werden sollen, einfach hintereinander geschrieben. Bei anderen Sprachen gibt es dafür eine begin-end-Konstruktion. Java hat eine solche Sprachkonstruktion, bei der für die Schlüsselwörter begin und end geschweifte Klammern verwendet werden. Seien A, B , ..., N Java-Befehle. Dann bedeutet die Schreibweise
dass die geklammerten Befehle sequenziell (einer nach dem anderen) abzuarbeiten sind. Der Wartegraph dazu sieht folgendermaßen aus, wobei die beiden Kringel vor und nach der Sequenz für die beiden Schlüsselsymbole { und } stehen sollen:
Für nebenläufige Programmabarbeitungen bieten manche Programmiersprachen gar keine Unterstützung. Manche Sprachen stellen eine - wie auch immer geschriebene - parbegin-parend-Konstruktion zur Verfügung. Ein Ausdruck wie
bedeutet dann, dass die geklammerten Befehle nebenläufig abgearbeitet werden dürfen. Zu dieser Sprachkonstruktion gehört der folgende Wartegraph, bei dem die beiden Kringel die beiden Schlüsselwörter parbegin und parend andeuten sollen:
Diese Sprachkonstruktion ist zwar sehr gut strukturiert, doch leider können mit ihr (zusammen mit der begin-end-Konstruktion) nicht alle Wartegraphen umgesetzt werden. Wenn Wartegraphen nur aus den beiden Strukturelementen begin-end und parbegin-parend aufgebaut werden dürfen, dann können nur solche Wartegraphen entstehen, bei denen zu jedem Kästchen (zu jedem zeitlichen Ablauf) genau ein Pfeil hin- und von jedem Kästchen genau ein Pfeil wegführt. Damit können Wartegraphen wie der folgende nicht aufgebaut werden:
Er beschreibt eine Situation, bei der mit der Abarbeitung des Befehls oder der Befehlsfolge C darauf gewarten werden muss, bis sowohl die Abarbeitung von A als auch die von B bendet ist. Die Abarbeitung von D hingegen muss lediglich auf das Ende der von B warten.
Java kennt keine parbegin-parend-Konstruktion, sondern verwendet ein Thread-Konzept zusammen mit den Steuermethoden start() und join(). Damit können alle Wartegraphen in ein Programm umgesetzt werden, allerdings auf Kosten der Programmstruktur. Das Thread-Konzept und die start()-join()-Konstruktion von Java werden im nächsten Abschnitt vorgestellt.