Atomic types
Table des matières |
Syntaxe
_Atomic
(
type-name
)
|
(1) | (depuis C11) | |||||||
_Atomic
type-name
|
(2) | (depuis C11) | |||||||
const
,
volatile
, et
restrict
, bien que contrairement aux autres qualificateurs, la version atomique de
type-name
puisse avoir une taille, un alignement et une représentation d'objet différents.
| type-name | - | tout type autre que tableau ou fonction. Pour (1) , type-name ne peut pas non plus être atomique ou qualifié cvr |
L'en-tête <stdatomic.h> définit de nombreux alias de types pratiques , de atomic_bool à atomic_uintmax_t , qui simplifient l'utilisation de ce mot-clé avec les types intégrés et les types de bibliothèque.
_Atomic const int* p1; // p est un pointeur vers un const int atomique const atomic_int* p2; // identique const _Atomic(int)* p3; // identique
Si la macro constante __STDC_NO_ATOMICS__ est définie par le compilateur, le mot-clé _Atomic n'est pas fourni.
Explication
Les objets de types atomiques sont les seuls objets exempts de courses aux données ; c'est-à-dire qu'ils peuvent être modifiés par deux threads simultanément ou modifiés par un thread et lus par un autre.
Chaque objet atomique possède son propre
ordre de modification
associé, qui est un ordre total des modifications apportées à cet objet. Si, du point de vue d'un thread, la modification
A
d'un certain atomique
M
se produit-avant
la modification
B
du même atomique
M
, alors dans l'ordre de modification de
M
,
A
se produit avant
B
.
Notez que bien que chaque objet atomique ait son propre ordre de modification, il n'existe pas d'ordre total unique ; différents threads peuvent observer les modifications d'objets atomiques différents dans des ordres différents.
Il existe quatre types de cohérence garantis pour toutes les opérations atomiques :
-
Cohérence écriture-écriture
: Si une opération
Aqui modifie un objet atomiqueMse produit avant une opérationBqui modifieM, alorsAapparaît avantBdans l'ordre de modification deM. -
Cohérence lecture-lecture
: Si un calcul de valeur
Ad'un objet atomiqueMse produit avant un calcul de valeurBdeM, etAprend sa valeur d'un effet secondaireXsurM, alors la valeur calculée parBest soit la valeur stockée parX, soit la valeur stockée par un effet secondaireYsurM, oùYapparaît aprèsXdans l'ordre de modification deM. -
Cohérence lecture-écriture
: Si un calcul de valeur
Ad'un objet atomiqueMse produit avant une opérationBsurM, alorsAprend sa valeur d'un effet secondaireXsurM, oùXapparaît avantBdans l'ordre de modification deM. -
Cohérence écriture-lecture
: Si un effet secondaire
Xsur un objet atomiqueMse produit avant un calcul de valeurBdeM, alors l'évaluationBprend sa valeur deXou d'un effet secondaireYqui apparaît aprèsXdans l'ordre de modification deM.
Certaines opérations atomiques sont également des opérations de synchronisation ; elles peuvent avoir des sémantiques de libération supplémentaires, des sémantiques d'acquisition ou des sémantiques séquentiellement cohérentes. Voir memory_order .
Les opérateurs intégrés d'incrémentation et de décrémentation et d'affectation composée sont des opérations atomiques de lecture-modification-écriture avec un ordonnancement séquentiel cohérent total (comme s'ils utilisaient memory_order_seq_cst ). Si des sémantiques de synchronisation moins strictes sont souhaitées, les fonctions de la bibliothèque standard peuvent être utilisées à la place.
Les propriétés atomiques ne sont significatives que pour les expressions lvalue . La conversion lvalue-vers-rvalue (qui modélise une lecture de mémoire depuis un emplacement atomique vers un registre CPU) supprime l'atomicité ainsi que les autres qualificateurs.
|
Cette section est incomplète
Motif : besoin de plus de détails, réviser l'interaction avec memory_order et les pages de la bibliothèque atomique |
Notes
Accéder à un membre d'une structure/union atomique est un comportement indéfini.
Le type de bibliothèque sig_atomic_t ne fournit pas de synchronisation inter-thread ni d'ordonnancement de la mémoire, seulement l'atomicité.
Les types
volatile
ne fournissent pas la synchronisation inter-threads, l'ordonnancement de la mémoire ou l'atomicité.
Il est recommandé que les implémentations garantissent que la représentation de
_Atomic
(
T
)
en C soit identique à celle de
std
::
atomic
<
T
>
en C++ pour tout type possible
T
. Les mécanismes utilisés pour assurer l'atomicité et l'ordonnancement de la mémoire devraient être compatibles.
Mots-clés
Exemple
#include <stdatomic.h> #include <stdio.h> #include <threads.h> atomic_int acnt; int cnt; int f(void* thr_data) { for (int n = 0; n < 1000; ++n) { ++cnt; ++acnt; // pour cet exemple, l'ordre de mémoire relâché est suffisant, par exemple // 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); }
Sortie possible :
The atomic counter is 10000 The non-atomic counter is 8644
Références
- Norme C23 (ISO/IEC 9899:2024):
-
- 6.7.2.4 Spécificateurs de type atomique (p: TBD)
-
- 7.17 Atomics <stdatomic.h> (p: TBD)
- Norme C17 (ISO/CEI 9899:2018) :
-
- 6.7.2.4 Spécificateurs de type atomique (p: 87)
-
- 7.17 Atomics <stdatomic.h> (p: 200-209)
- Norme C11 (ISO/CEI 9899:2011) :
-
- 6.7.2.4 Spécificateurs de type atomique (p: 121)
-
- 7.17 Atomics <stdatomic.h> (p: 273-286)
Voir aussi
| Bibliothèque de support de la concurrence | |
|
Documentation C++
pour
atomic
|