GCC prend en charge les opérations atomiques :
gcc atomique
CCG __atomic_*
intégrés
Depuis GCC 4.8, __sync
les éléments intégrés ont été dépréciés au profit du __atomic
intégrés :https://gcc.gnu.org/onlinedocs/gcc-4.8.2/gcc/_005f_005fatomic-Builtins.html
Ils implémentent le modèle de mémoire C++ et std::atomic
les utilise en interne.
L'exemple de threads POSIX suivant échoue systématiquement avec ++
sur x86-64, et fonctionne toujours avec _atomic_fetch_add
.
main.c
#include <assert.h>
#include <pthread.h>
#include <stdlib.h>
enum CONSTANTS {
NUM_THREADS = 1000,
NUM_ITERS = 1000
};
int global = 0;
void* main_thread(void *arg) {
int i;
for (i = 0; i < NUM_ITERS; ++i) {
__atomic_fetch_add(&global, 1, __ATOMIC_SEQ_CST);
/* This fails consistently. */
/*global++*/;
}
return NULL;
}
int main(void) {
int i;
pthread_t threads[NUM_THREADS];
for (i = 0; i < NUM_THREADS; ++i)
pthread_create(&threads[i], NULL, main_thread, NULL);
for (i = 0; i < NUM_THREADS; ++i)
pthread_join(threads[i], NULL);
assert(global == NUM_THREADS * NUM_ITERS);
return EXIT_SUCCESS;
}
Compiler et exécuter :
gcc -std=c99 -Wall -Wextra -pedantic -o main.out ./main.c -pthread
./main.out
Analyse de désassemblage à :Comment démarrer des threads en C ordinaire ?
Testé dans Ubuntu 18.10, GCC 8.2.0, glibc 2.28.
C11 _Atomic
En 5.1, le code ci-dessus fonctionne avec :
_Atomic int global = 0;
global++;
Et C11 threads.h
a été ajouté dans la glibc 2.28, qui vous permet de créer des threads en C ANSI pur sans POSIX, exemple exécutable minimal :Comment démarrer des threads en C ordinaire ?