Gibt es in C einen (POSIX-)portablen Weg für atomare Variablenoperationen ähnlich einem portablen Threading mit pthread?
Atomare Operationen sind Operationen wie “increment and get”, die atomar ausgeführt werden, was bedeutet, dass kein Kontextwechsel die Operation stören kann. Im Linux-Kernel-Raum müssen wir atomar_t Typ, in Java haben wir die java.util.concurrent.atomic Paket.
Unter Linux bietet die Datei atomic.h atomare Operationen, aber das Include ist plattformabhängig, z #include <asm-x86_64/atomic.h> und es ist auf ähnliche Weise unter Mac OS X nicht verfügbar.
Ab C11 gibt es eine optionale Atombibliothek die atomare Operationen bereitstellt. Dies ist auf jede Plattform portierbar, die einen C11-Compiler (wie gcc-4.9) mit dieser optionalen Funktion hat.
Das Vorhandensein des Atoms kann mit überprüft werden __STDC_NO_ATOMICS__und das Vorhandensein von <stdatomic.h>
atomar.c
#include <stdio.h>
#include <stdlib.h>
#ifndef __STDC_NO_ATOMICS__
#include <stdatomic.h>
#endif
int main(int argc, char**argv) {
_Atomic int a;
atomic_init(&a, 42);
atomic_store(&a, 5);
int b = atomic_load(&a);
printf("b = %i\n", b);
return EXIT_SUCCESS;
}
Compiler-Aufrufe
clang -std=c11 atomic.c
gcc -std=c11 atomic.c
Für alle, die in Zukunft darauf stoßen, sind C11-Atomics der beste Weg, dies jetzt zu tun – ich glaube, sie werden in GCC 4.9 enthalten sein.
Können Sie das erweitern?
– GraphicsMuncher
25. November 2013 um 20:30 Uhr
Beispiel für minimal lauffähige C11-Atomics + -Threads: stackoverflow.com/questions/1130018/…
– Ciro Santilli OurBigBook.com
13. Februar 2019 um 22:08 Uhr
Da Sie nach OS X gefragt haben:
(und da Cross-Plattformity in diesem Thread angesprochen wurde.)
OS X hat Funktionen OSAtomicAdd32() und Freunde. Sie sind in “/usr/include/libkern/OSAtomic.h” deklariert. Sehen Der Threading-ProgrammierleitfadenAbschnitt “Verwendung atomarer Operationen”.
Und für Windows gibt es InterlockedIncrement() und Freunde (siehe MSDN).
Zusammen mit den gcc builtins __sync_fetch_and_add() and friends (wurde oben verlinkt), sollten Sie für jede Haupt-Desktop-Plattform etwas haben.
Bitte beachten Sie, dass ich sie selbst noch nicht verwendet habe, dies aber möglicherweise in den nächsten Tagen tun werde.
Nein, POSIX spezifiziert nicht irgendein portable lock-freie/atomare Operationen. Deshalb haben sie pthreads.
Sie müssen entweder nicht standardmäßige Methoden verwenden oder sich aus Gründen der Portabilität an ptrheads halten.
Ciro Santilli OurBigBook.com
C11 Atomics minimal lauffähiges Beispiel
Mit der Hinzufügung von Threads in glibc 2.28 können wir sowohl Atomic als auch Threading in reinem C11 durchführen.
#include <stdio.h>
#include <threads.h>
#include <stdatomic.h>
atomic_int acnt;
int cnt;
int f(void* thr_data)
{
for(int n = 0; n < 1000; ++n) {
++cnt;
++acnt;
// for this example, relaxed memory order is sufficient, e.g.
// atomic_fetch_add_explicit(&acnt, 1, memory_order_relaxed);
}
return 0;
}
int main(void)
{
thrd_t thr[10];
for(int n = 0; n < 10; ++n)
thrd_create(&thr[n], f, NULL);
for(int n = 0; n < 10; ++n)
thrd_join(thr[n], NULL);
printf("The atomic counter is %u\n", acnt);
printf("The non-atomic counter is %u\n", cnt);
}
Kompilieren und ausführen:
gcc -std=c11 main.c -pthread
./a.out
Mögliche Ausgabe:
The atomic counter is 10000
The non-atomic counter is 8644
Der nicht-atomare Zähler ist sehr wahrscheinlich kleiner als der atomare, da der Zugriff über Threads hinweg auf die nicht-atomare Variable sehr schnell erfolgt.
Ein pthreads-Beispiel finden Sie unter: How do I start threads in plain C?
Getestet in Ubuntu 18.04 (glibc 2.27) durch Kompilieren von glibc aus der Quelle: Mehrere glibc-Bibliotheken auf einem einzelnen Host Ubuntu 18.10 hat glibc 2.28, also sollten die Dinge dort einfach funktionieren.
Aber für den Fall, dass wir bei glibc 2.27 bleiben, würde stdatomic funktionieren pthreads?
– Irgendein Name
8. April 2019 um 18:52 Uhr
glibc 2.28 wird mit Ubuntu 18.10 oder 19.04 geliefert
– junghm
21. Mai 2019 um 14:56 Uhr
Göz
AFAIK gibt es keine plattformübergreifenden Möglichkeiten, atomare Operationen durchzuführen. Vielleicht gibt es da draußen eine Bibliothek, aber ich weiß nichts davon. Es ist jedoch nicht besonders schwierig, Ihre eigenen zu rollen.
Aber für den Fall, dass wir bei glibc 2.27 bleiben, würde stdatomic funktionieren pthreads?
– Irgendein Name
8. April 2019 um 18:52 Uhr
glibc 2.28 wird mit Ubuntu 18.10 oder 19.04 geliefert
– junghm
21. Mai 2019 um 14:56 Uhr
entspannen
Ich glaube nicht, dass es das gibt.
Eine Möglichkeit, dies zu lösen, sofern die Lizenzen dies natürlich zulassen, wäre, die relevanten Implementierungen pro Architektur beispielsweise aus dem Linux-Kernel-Space zu kopieren. Ich habe die Entwicklung dieser Primitiven nicht genau verfolgt, aber ich würde vermuten, dass sie tatsächlich Primitiven sind, dh nicht von anderen Diensten oder APIs im Kernel abhängen.
Es gibt einige GCC-Einbauten, hier beschrieben.
– Café
15. Juli 2009 um 8:09 Uhr
Schön, beschränkt auf GCC, aber für mich wäre es in Ordnung.
– Meister
15. Juli 2009 um 8:14 Uhr
und hier für neuere gcc: gcc.gnu.org/onlinedocs/gcc/_005f_005fatomic-Builtins.html
– osgx
24. November 2011 um 0:18 Uhr