Programmiersprache: Swift startet ersten Akt zum Actor-Modell

Auf GitHub findet eine Diskussion zur Einführung des Aktorenmodells für den sicheren Datenaustausch in nebenläufigen Programmen für Swift statt.

In Pocket speichern vorlesen Druckansicht 10 Kommentare lesen
Lesezeit: 3 Min.

Apples Programmiersprache Swift könnte bald das Konzept des Actor-Modells einführen. Auf GitHub findet sich ein konkreter Vorschlag zum Einführen des Ansatzes, der auf Nachrichtenaustausch setzt, um typische Fallen der Parallelprogrammierung wie Data Races zu vermeiden. Andere Programmiersprachen wie Scala, Erlang oder D implementieren das Aktorenmodell bereits.

Aktoren verhalten sich in dem Modell ähnlich wie Klassen, schützen aber die veränderlichen Werte vor externem Zugriff. Nachrichten ersetzen die direkten Funktionsaufrufe. Der Aktor kümmert sich um die Verarbeitung, sobald dies ohne potenzielle Race Conditions möglich ist. Jeder Actor hat seine eigene Mailbox oder Message Queue, die alle Nachrichten aufnimmt, bis der Aktor sie bearbeiten kann.

Der nun veröffentlichte Vorschlag konkretisiert einen Teil der im November vom Swift-Team veröffentlichten Roadmap zur nebenläufigen Programmierung. Die Erweiterungen sind für Swift 6 geplant. Derzeit ist Swift 5.3 aktuell, und in Kürze sollte Version 5.4 erscheinen, die den Fokus auf Qualitätssicherung und Perfomanceverbesserung legt.

Wettrennen um die Werte: Race Conditions und Data Races

In der nebenläufigen Programmierung sind Race Conditions ein typisches Problem des nichtdeterministischen Verhaltens: Wenn zwei parallel laufende Threads beispielsweise Berechnungen auf einer globalen Variable ausführen, kann es zu Fehlern kommen, die jedoch nicht immer auftreten. Für den simplen Fall, dass beide Threads den Wert zunächst auslesen, dann mit 2 multiplizieren und schließlich in dieselbe Variable zurückschreiben, ergibt sich im korrekten Fall für den Ausgangswert 1 ein Ergebnis von 4.

Voraussetzung dafür ist, dass zunächst ein Thread die Variable mit dem Wert 1 ausliest, mit 2 multipliziert und anschließend das Ergebnis 2 schreibt, bevor der zweite Thread diese 2 ausliest, erneut mit 2 multipliziert und anschließend eine 4 schreibt. Falls jedoch der zweite Thread den Wert ausliest, wenn der erste bereits gelesen, aber das Ergebnis noch nicht geschrieben hat, rechnen beide mit dem Ausgangswert 1 und schreiben im Anschluss die 2 als falsches Endergebnis in die Variable zurück.

Data Races beschreiben, dass ein Speicherzugriff in einem Thread potenziell in für den korrekten Programmablauf gefährlichen oder störenden Weise von einer Schreiboperation auf denselben Speicherbereich in einem anderen Thread beeinflusst wird. Sie gelten in manchen Definitionen als Teilbereich der Race Conditions, während andere sie als eigenständiges Problem betrachten.

Gegen Race Conditions helfen Lock-Mechanismen, die auch Swift bietet. Motivation für den Vorschlag zum Aktorenmodell ist, dass der sichere Einsatz von Klassen mit veränderlichen Inhalten in nebenläufigen Programmen umständlich und fehleranfällig ist.

Nach den Entwürfen im GitHub-Proposal soll Swift actors einfügen, die sich weitgehend wie Klassen verhalten: Sie können Methoden, Properties und Subscripts aufweisen. Letztere sind eine Besonderheit in Swift als vereinfachter Weg zum Zugriff auf Elemente in Collections. Aktoren können auch mit Generics genutzt werden oder ihrerseits generisch sein.

Im Gegensatz zu regulären Klassen greift für sie der Prozess der Actor Isolation, der den Inhalt vor Data Races schützt. Der Swift-Compiler erlaubt den Zugriff auf die meisten Inhalte nur aus self und spuckt bei dem Versuch eines externen Zugriffs beziehungsweise Aufrufs auf Properties oder Methoden einen Fehler aus.

Zugriffe von außen sind über zwei Wege erlaubt. Zum einen lassen sich unveränderliche (immutable) Werte abrufen, da sich der Zustand per Definition nicht ändert, was einen Data Race ausschließt. Alle anderen Aufrufe erfolgen nicht direkt, sondern asynchron über Nachrichten.

Jeder Actor verwaltet seinen eigenen Posteingang und verarbeitet die Nachrichten sequenziell. Dabei findet niemals eine parallele Verarbeitung von Actor-isoliertem Code statt, um Race Conditions zu verhindern. Die aufrufende Methode kann bei Bedarf so lange pausieren, bis der Aktor den Aufruf verarbeitet hat. Um die Isolierung der Aktoren kümmert sich der Compiler. Er stellt sicher, dass Zugriffe nur auf unveränderliche Werte oder über das Nachrichtensystem erfolgen.

Weitere Details inklusive Codebeispielen lassen sich dem Proposal SE-0306 entnehmen, das sich bis zum 29. März 2021 in der Reviewphase befindet. Wer sich bis dahin an der Diskussion beteiligen möchte, findet weitere Informationen im offiziellen Swift-Forum.

(rme)