C Language
Atomik
Suche…
Syntax
-
#ifdef __STDC_NO_ATOMICS__
-
# error this implementation needs atomics
-
#endif
-
#include <stdatomic.h>
- vorzeichenloser _Atomic Counter = ATOMIC_VAR_INIT (0);
Bemerkungen
Atomics als Teil der C-Sprache ist eine optionale Funktion, die seit C11 verfügbar ist.
Ihr Zweck ist es, einen rennfreien Zugriff auf Variablen zu gewährleisten, die von verschiedenen Threads gemeinsam genutzt werden. Ohne atomare Qualifizierung wäre der Status einer gemeinsam genutzten Variablen undefiniert, wenn zwei Threads gleichzeitig darauf zugreifen. Eine Inkrementierungsoperation ( ++
) könnte beispielsweise in mehrere Assembler-Anweisungen, einen Lesevorgang, den Zusatz selbst und einen Speicherbefehl aufgeteilt werden. Wenn ein anderer Thread dieselbe Operation ausführen würde, könnten die beiden Befehlssequenzen miteinander verflochten werden und zu einem inkonsistenten Ergebnis führen.
Typen: Alle Objekttypen mit Ausnahme von
_Atomic
können mit_Atomic
qualifiziert_Atomic
.Operatoren: Alle Operatoren zum Lesen, Ändern und Schreiben (z. B.
++
oder*=
) sind garantiert atomar.Operationen: Es gibt einige andere Operationen, die als generische Funktionen des Typs angegeben sind, z. B.
atomic_compare_exchange
.Threads: Der Zugriff darauf wird garantiert nicht zu einem Datenrennen führen, wenn von verschiedenen Threads darauf zugegriffen wird.
Signalhandler: Atomic-Typen werden als sperrungsfrei bezeichnet, wenn alle Operationen auf ihnen zustandslos sind. In diesem Fall können sie auch verwendet werden, um Zustandsänderungen zwischen dem normalen Steuerfluss und einem Signalhandler zu behandeln.
Es gibt nur einen Datentyp, der garantiert
atomic_flag
:atomic_flag
. Dies ist ein minimaler Typ, dessen Operationen dazu bestimmt sind, effiziente Test-and-Set-Hardwareanweisungen abzubilden.
Andere mtx_t
zur Vermeidung von Race-Bedingungen sind in der Thread-Schnittstelle von C11 verfügbar, insbesondere ein Mutex-Typ mtx_t
, um Threads gegenseitig vom Zugriff auf kritische Daten oder kritische Codeabschnitte auszuschließen. Wenn keine Atomik verfügbar ist, müssen diese verwendet werden, um Rassen zu verhindern.
Atomik und Operatoren
Auf atomare Variablen kann gleichzeitig zwischen verschiedenen Threads zugegriffen werden, ohne dass Race-Bedingungen erstellt werden.
/* a global static variable that is visible by all threads */
static unsigned _Atomic active = ATOMIC_VAR_INIT(0);
int myThread(void* a) {
++active; // increment active race free
// do something
--active; // decrement active race free
return 0;
}
Alle lvalue-Operationen (Operationen, die das Objekt ändern), die für den Basistyp zulässig sind, sind zulässig und führen nicht zu Race-Bedingungen zwischen verschiedenen Threads, die auf sie zugreifen.
- Operationen an atomaren Objekten sind in der Regel um Größenordnungen langsamer als normale Rechenoperationen. Dies umfasst auch einfache Lade- oder Speicheroperationen. Sie sollten sie daher nur für kritische Aufgaben verwenden.
- Übliche arithmetische Operationen und Zuweisungen wie
a = a+1;
In der Tat gibt es drei Operationen aufa
: zuerst eine Ladung, dann eine Addition und schließlich ein Geschäft. Dies ist nicht frei von Rennen. Nur die Operationa += 1;
unda++;
sind.