Multicore-Programmierung

Ohne Locks für Multicore-Systeme programmieren

| Autor / Redakteur: David Kalinsky * / Hendrik Härter

CAS prüft und aktualisiert kritische Variablen und Pointer

Das Code-Snippet oben zeigt eine CAS-Operation, dargestellt in einer C-ähnlichen Sprache. CAS vergleicht den aktuellen Inhalt von "var" mit einem "expected"-Wert. Ist der Wert wie erwartet (expected), wird "var" aktualisiert und damit "new". Ansonsten wird ‘var’ nicht aktualisiert. All dies erfolgt in einer einzigen, kontinuierlichen Operation.

Bei der Entwicklung von lockfreiem Code wird zuerst der Originalwert einer Variable (oder eines Zeigers) in "expected" kopiert. Dann wird durch einen weiteren Kopiervorgang in einer (möglicherweise langen und komplexen) Kalkulation ein "new"-Wert für die Variable erzeugt. Während der Verarbeitung hat aber vielleicht ein anderer Task – eventuell auf einem anderen Kern – den Originalwert der Variable schon geändert. Die Variable soll aber nur dann mit dem "new"-Wert aktualisiert werden, wenn sie zwischenzeitlich nicht durch einen anderen Task geändert wurde. CAS nimmt eine gemeinsame Überprüfung und Aktualisierung vor, ohne dass ein Lock-Konstrukt nötig ist.

Wenn CAS erkennt, dass die Variable nicht mehr den Original- oder "expected"-Wert hat, entscheidet die Applikationssoftware über die nächsten Schritte. Die Varianle wurde nicht mit dem "new"-Wert aktualisiert. Hier wird oft die gesamte Kalkulation wiederholt, diesmal basierend auf einem erneuten Auslesen des aktuellen Wertes der Variable. Dann wird wieder die CAS-Operation aufgerufen, um sicherzustellen, dass nun kein anderer Task den Wert verändert hat.

Beispiel 1: Erhöhen eines Zählwerts

Zunächst ein einfaches Beispiel: Zwei Tasks erhöhen beide einen Wert mittels des „++“-Operators aus der C-Sprache.

In einer Multicore-Umgebung können beide Tasks gleichzeitig aktiv werden, ob sie nun die gleiche Priorität haben oder nicht. Manchmal werden die ++-Operationen in beiden Tasks zur gleichen Zeit ausgeführt. Dadurch wird der im Zähler (counter) gespeicherte Wert beschädigt, oder es geht z. B. eine Erhöhung verloren.

Dies lässt sich umgehen, indem ein Lock verwendet wird, das die ++-Operation als kritische Sektion schützt. Wir wollen doch aber lockfrei programmieren! Der Beispielcode oben rechts zeigt, wie sich das gleiche Ziel lockfrei erreichen lässt

Dabei ist es unerheblich, ob die Operation „+1“ atomisch ist. Wichtig ist nur, ob eine andere Task die Variable "counter" während der Kalkulation manipuliert hat. Die CAS-Operation überprüft dies und aktualisiert "counter" nur, wenn keine Manipulation stattgefunden hat. Sonst wird dieser Code wieder an den Anfang zurückgeführt, und es findet ein weiterer Erhöhungsvorgang statt.

Dieser Code ist viel komplexer als sein lockbasiertes Gegenstück. Damit ist es auch schwieriger, ihn zu verstehen und zu debuggen. Zum anderen ist aufgrund des Schleifen-Verhaltens in diesem Code die Ausführungszeit nicht kontrollierbar (wenn immer wieder Manipulationen erkannt werden). Für Systeme mit harter Echtzeit eignet sich diese Programmiermethode oft nicht.

In manchen Applikationen lässt sich die Anzahl der Schleifeniterationen und damit die Worst-Case-Ausführungszeit begrenzen. Hierfür ist ggf. eine Wahrscheinlichkeitsberechnung erforderlich, die belegt, dass die maximale Anzahl der Iterationen möglichst selten erreicht wird.

Lesen Sie weiter: Beispiel 2 - Lockfreie verknüpfte Liste und das Fazit

Inhalt des Artikels:

Kommentar zu diesem Artikel abgeben
Wenn ich auf "Artikel als PDF" gehe, kommen die Bilder groß nach dem Artikel (Seiten 5 und 6).  lesen
posted am 20.09.2011 um 08:50 von SLiebing

Ein toller Artikel, den ich mir gerne aufheben möchte. Leider sind die als Erklärung enthaltenen...  lesen
posted am 20.09.2011 um 08:09 von folco


Mitdiskutieren
copyright

Dieser Beitrag ist urheberrechtlich geschützt. Sie wollen ihn für Ihre Zwecke verwenden? Infos finden Sie unter www.mycontentfactory.de (ID: 28901070 / Software-Entwurf & Echtzeit-Design)