Einfachere Concurrency, Skalierbarkeit und Remoting durch Actors

Akka - Actors auf der JVM

Mathias Doenitz


Die Jahre 2005 bis 2010 markieren eine Zeitenwende in der Geschichte der Softwareentwicklung. Mehr als drei Jahrzehnte lang konnten wir uns darauf verlassen, dass unsere Programme quasi automatisch von den Fortschritten in der Hardwareentwicklung profitieren. Lief ein Stückchen Code nicht schnell genug, würde ihm die nächste CPU-Generation schon „Beine machen“. Diese Zeiten sind mittlerweile vorbei [2].

Größere Fortschritte in der Single Thread Performance sind nicht mehr zu erwarten und, obwohl Moore’s Law (die Verdoppelung der Transistorzahl auf ICs ca. alle zwei Jahre) nach wie vor gilt, ist es mittlerweile Amdahl’s Law (Abb. 1), das uns Probleme macht: Ohne eine Minimierung von nicht parallelisierten Programmteilen wird unser Code aktuelle und vor allem zukünftige Prozessorgenerationen nur noch gering auslasten können.

Abb. 1: Programme profitieren von vielen CPU Cores nur bei hohem Anteil an parallelen Code (Quelle: [3], Creative Commons)

Nun bietet Java schon seit vielen Jahren Werkzeuge, um die Programmausführung auf mehrere Threads zu verteilen. Wie allerdings die Meisten, die Erfahrungen mit dieser Art der Programmierung gemacht haben, bestätigen werden, ist das korrekte und performante Design von größeren, nebenläufigen Algorithmen über Threadpools, Locks, Mutexes und Semaphores alles andere als ein Kinderspiel. Allzu oft verwendet man große Anstrengungen auf das Beheben von kleinen, schwer zu findenden Fehlern, die irgendwo zu einer Race Condition führen und das Programm in ein nicht deterministisches „Logikmonster“ verwandeln. Wenn dies dann schließlich mit noch mehr Locks, synchronisierten und volatilen Markern gezähmt zu sein scheint, stellt man nicht selten fest, dass die Performance doch deutlich hinter den Erwartungen zurückbleibt.

Ein Teil des Problems liegt hierbei sicherlich in der inhärenten Komplexität paralleler Algorithmen. Mit einem anderen Programmiermodell lassen sich allerdings viele potenzielle Stolpersteine von vornherein aus dem Weg räumen. Zwei Ansätze haben sich dabei bisher als vielversprechend erwiesen: Ein eher funktionaler als imperativer Programmierstil und das Actor-Modell. Beide haben zum Ziel, die Hauptursache von Multi-Threading-Problemen zu eliminieren: den so genannten Shared Mutable State, also den gemeinsamen Zugriff mehrerer Threads auf veränderliche Variablen.

Der funktionale Ansatz zielt dabei auf das „Mut­able“ im Shared Mutable State, also auf die Veränderlichkeit von Objekten und Variablen über die Zeit de...

Einfachere Concurrency, Skalierbarkeit und Remoting durch Actors

Akka - Actors auf der JVM

Mathias Doenitz


Die Jahre 2005 bis 2010 markieren eine Zeitenwende in der Geschichte der Softwareentwicklung. Mehr als drei Jahrzehnte lang konnten wir uns darauf verlassen, dass unsere Programme quasi automatisch von den Fortschritten in der Hardwareentwicklung profitieren. Lief ein Stückchen Code nicht schnell genug, würde ihm die nächste CPU-Generation schon „Beine machen“. Diese Zeiten sind mittlerweile vorbei [2].

Größere Fortschritte in der Single Thread Performance sind nicht mehr zu erwarten und, obwohl Moore’s Law (die Verdoppelung der Transistorzahl auf ICs ca. alle zwei Jahre) nach wie vor gilt, ist es mittlerweile Amdahl’s Law (Abb. 1), das uns Probleme macht: Ohne eine Minimierung von nicht parallelisierten Programmteilen wird unser Code aktuelle und vor allem zukünftige Prozessorgenerationen nur noch gering auslasten können.

Abb. 1: Programme profitieren von vielen CPU Cores nur bei hohem Anteil an parallelen Code (Quelle: [3], Creative Commons)

Nun bietet Java schon seit vielen Jahren Werkzeuge, um die Programmausführung auf mehrere Threads zu verteilen. Wie allerdings die Meisten, die Erfahrungen mit dieser Art der Programmierung gemacht haben, bestätigen werden, ist das korrekte und performante Design von größeren, nebenläufigen Algorithmen über Threadpools, Locks, Mutexes und Semaphores alles andere als ein Kinderspiel. Allzu oft verwendet man große Anstrengungen auf das Beheben von kleinen, schwer zu findenden Fehlern, die irgendwo zu einer Race Condition führen und das Programm in ein nicht deterministisches „Logikmonster“ verwandeln. Wenn dies dann schließlich mit noch mehr Locks, synchronisierten und volatilen Markern gezähmt zu sein scheint, stellt man nicht selten fest, dass die Performance doch deutlich hinter den Erwartungen zurückbleibt.

Ein Teil des Problems liegt hierbei sicherlich in der inhärenten Komplexität paralleler Algorithmen. Mit einem anderen Programmiermodell lassen sich allerdings viele potenzielle Stolpersteine von vornherein aus dem Weg räumen. Zwei Ansätze haben sich dabei bisher als vielversprechend erwiesen: Ein eher funktionaler als imperativer Programmierstil und das Actor-Modell. Beide haben zum Ziel, die Hauptursache von Multi-Threading-Problemen zu eliminieren: den so genannten Shared Mutable State, also den gemeinsamen Zugriff mehrerer Threads auf veränderliche Variablen.

Der funktionale Ansatz zielt dabei auf das „Mut­able“ im Shared Mutable State, also auf die Veränderlichkeit von Objekten und Variablen über die Zeit de...

Neugierig geworden?


    
Loading...

Angebote für Teams

Für Firmen haben wir individuelle Teamlizenzen. Wir erstellen Ihnen gerne ein passendes Angebot.

Das Library-Modell:
IP-Zugang

Das Company-Modell:
Domain-Zugang