Oliver Heger Bosch Software Innovations

Das Framework Akka bietet eine effiziente und vollständige Implementierung des Aktorenmodells.

Um moderne Hardware effizient zu nutzen, müssen Entwickler sie möglichst so aufbauen, dass sie mit parallelen Prozessen zurechtkommt. Und das auch noch möglichst effizient. Das ist leider einfacher gesagt als getan, sind unsere Entwicklerhirne doch eher auf sequenzielle Abläufe ausgerichtet. Das Framework Akka tritt an, die Entwicklung paralleler Anwendungen zu erleichtern.

Java brachte bereits in der ersten Version Unterstützung für Programme, die in mehreren Threads ablaufen können. Diese kam in Form von Schlüsselwörtern (wie synchronized oder volatile), Klassen der Standardbibliothek (z. B. Thread oder ThreadGroup) oder Methoden in Object (wie wait oder notify). Wer jedoch bereits versucht hat, mit diesen Bordmitteln komplexe nebenläufige Logik zu orchestrieren, der weiß, dass sie auf einem sehr niedrigen Abstraktionsniveau angesiedelt sind. Daher ist es schwierig, das korrekte Maß an Synchronisierung zu finden: Gerade ausreichend, um die Integrität der Daten sicherzustellen und den teilweise subtilen Anforderungen des Java-Memory-Modells zu genügen, aber auch nicht mehr als nötig, um die vorhandene Rechenleistung nicht auszubremsen.

Seit Java 5 hat sich die Situation etwas gebessert: Hier kam das util.concurrent-Paket hinzu mit speziell für parallele Anwendungsfälle optimierten Datenstrukturen (z. B. ConcurrentMap oder Queues) und Unterstützung für Threadpools und Synchronisationsprimitiva auf einem höheren Niveau (z. B. CountdownLatch oder Semaphore). Der grundlegende Ansatz zur Nebenläufigkeit ist aber gleich geblieben: Mehrere Threads greifen koordiniert auf gemeinsam genutzte Daten zu. Dies bringt einige Nachteile mit sich.

Es handelt sich dabei um einen dezentralen Ansatz. Jeglicher Datenzugriff muss entsprechend abgesichert sein. Das macht es schwierig, die Korrektheit der Anwendung zu verifizieren. Selbst wenn die Zugriffslogik auf Daten in einer Klasse gekapselt ist, kann eine einzige unbedachte Änderung genügen, um die Integrität der Daten zu korrumpieren. Mit Unit-Tests allein kann man sich dagegen oft nur schwer absichern.

Ein anderes Problem ist eher prinzipieller Natur: Die gemeinsame Nutzung von Daten durch mehrere Threads impliziert, dass manche Threads mitunter auf andere warten müssen, um ihre Operationen ungestört ausführen zu können. Nun sind Threads aber relativ teure Ressourcen und eigentlich zu schade dafür, untätig auf einen freien Zeitpunkt zum Datenzugriff zu warten. Zumal das Parken und spätere Reaktivieren eines Threads mit einem gewissen Overhead verbunden ist. Idealerweise möchte man die zu erledigenden Aufgaben auf eine überschaubare Menge von Threads verteilen, die dann ohne Unterbrechung laufen und laufen wie ein bekanntes Automodell aus der Prä-Diesel-Skandal-Ära.

Den vollständigen Artikel lesen Sie in der Ausgabe:

Java Magazin 10.17 - "Java 9"

Alle Infos zum Heft
579810703Parallele Programme trotz sequentiellem Denken: Das Akka-Framework
X
- Gib Deinen Standort ein -
- or -