Atomare Operationen sind Anweisungen, die von außen nicht unterbrochen beobachtet werden können: Sie laufen entweder vollständig oder gar nicht. Der Name kommt von griechisch atomos = unteilbar. Sie sind die Hardware-Basis fast aller Synchronisations-Mechanismen.

Warum Atomarität nötig ist

Bei nebenläufigen Threads kann ein scheinbar einfacher Befehl wie i = i + 1 zwischen zwei Threads zerstückelt ablaufen: Lesen, Addieren, Zurückschreiben sind drei getrennte Schritte (read-modify-write). Genau diese Race Condition gehört in einen kritischen Abschnitt oder wird mit atomaren Operationen gelöst.

Atomare Primitive der Hardware

  • Test-and-Set: Setzt ein Flag auf 1 und liefert den alten Wert zurück — die Basis klassischer Spinlocks.
  • Fetch-and-Add: Addiert atomar auf eine Variable und liefert den alten Wert — ideal für Zähler.
  • Compare-and-Swap (CAS): Vergleicht den Speicherwert mit einem erwarteten Wert und tauscht nur bei Übereinstimmung; Grundlage lock-freier Datenstrukturen.
  • Load-Linked/Store-Conditional (LL/SC): Paar aus Lese- und bedingtem Schreibbefehl, das bei Änderung des Speicherworts zwischen beiden Schritten fehlschlägt.

Je nach Architektur heißen die Befehle anders: x86 nutzt das LOCK-Präfix (etwa LOCK CMPXCHG, LOCK XADD), ARM verwendet LDREX/STREX, RISC-V bietet eigene AMO-Instruktionen (Atomic Memory Operations).

Grenzen: ABA-Problem und Speicherordnung

CAS erkennt nicht, wenn sich ein Wert von A zu B und wieder zurück zu A ändert — das ABA-Problem. Lock-freie Algorithmen lösen es mit einem angehängten Zähler oder Versionstoken. Außerdem dürfen Compiler und CPU Speicheroperationen umsortieren; atomare Typen mit Speicherordnungs-Sematik (memory ordering) und Barrieren verhindern das.

Moderne Prozessoren sichern Atomarität über die Cache-Kohärenz (etwa das MESI-Protokoll): Solange die Cacheline exklusiv gehört, läuft die Operation lokal auf dem Kern; eine Änderung durch einen anderen Kern erzwingt Synchronisation. Ein Interrupt oder ein anderer Thread kann eine laufende atomare Operation nicht zerstückeln.

Atomare Typen in Programmiersprachen

C11 bringt <stdatomic.h> mit, C++11 std::atomic<T>, Java kennt AtomicInteger und verwandte Klassen, Go stellt das Paket sync/atomic bereit. Sie alle garantieren, dass Lese- und Schreibzugriffe auf den Typ atomar und korrekt geordnet ablaufen.

Für komplexere Anforderungen gibt es höhere Werkzeuge wie Semaphore, Mutex oder Monitore, die intern auf atomaren Operationen aufbauen.