Changer un pointeur est-il considéré comme une action atomique en C?

Si j’ai un programme multithread qui lit une mémoire de type cache par référence. Puis-je modifier ce pointeur par le thread principal sans risquer que les autres threads lisent des valeurs inattendues.

À mon avis, si le changement est atomique, les autres threads liront soit la valeur la plus ancienne, soit la valeur la plus récente; jamais de mémoire aléatoire (ou pointeurs nuls), non?

Je suis conscient que je devrais utiliser des méthodes de synchronisation de toute façon, mais je rest curieux.

Les changements de pointeur sont-ils atomiques?

Mise à jour: Ma plate-forme est Linux 64 bits (2.6.29), bien que j’aimerais également une réponse multiplate-forme 🙂

Comme d’autres l’ont mentionné, rien dans le langage C ne le garantit, et cela dépend de votre plate-forme.

Sur la plupart des plates-formes de bureau contemporaines, la lecture / écriture vers un emplacement aligné, de la taille d’un mot, sera atomique. Mais cela ne résout vraiment pas votre problème, car le processeur et le compilateur ont réorganisé les lectures et les écritures.

Par exemple, le code suivant est cassé:

Fil A:

DoWork(); workDone = 1; 

Fil B:

 while(workDone != 0); ReceiveResultsOfWork(); 

Bien que l’écriture sur workDone soit atomique, sur de nombreux systèmes, le processeur ne garantit pas que l’écriture sur workDone sera visible par les autres processeurs avant les écritures effectuées via DoWork() . Le compilateur peut également être libre de réordonner l’écriture sur workDone avant l’appel à DoWork() . Dans les deux cas, ReceiveResultsOfWork() peut commencer à fonctionner sur des données incomplètes.

En fonction de votre plate-forme, vous devrez peut-être insérer des barrières de mémoire, etc., pour garantir un bon ordre. Cela peut être très difficile à obtenir.

Ou utilisez simplement des serrures. Beaucoup plus simple, beaucoup plus facile à vérifier que correct, et dans la plupart des cas, assez performant.

Le langage C ne dit rien sur le sharepoint savoir si les opérations sont atomiques. J’ai travaillé sur des microcontrôleurs avec des bus 8 bits et des pointeurs 16 bits; toute opération de pointeur sur ces systèmes serait potentiellement non atomique. Je pense me souvenir d’Intel 386 (dont certains avaient des bus 16 bits) soulevant des préoccupations similaires. De même, je peux imaginer des systèmes dotés de processeurs 64 bits, mais de bus de données 32 bits, qui pourraient alors susciter des préoccupations similaires en ce qui concerne les opérations de pointeur non atomiques. (Je n’ai pas vérifié si de tels systèmes existaient réellement.)

EDIT: La réponse de Michael vaut la peine d’être lue. La taille du bus par rapport à la taille du pointeur n’est pas la seule considération à prendre en compte pour l’atomicité; c’était simplement le premier contre-exemple qui me vint à l’esprit.

Vous n’avez pas mentionné une plate-forme. Je pense donc qu’une question un peu plus précise serait

Les changements de pointeur sont-ils garantis atomiques?

La distinction est nécessaire car différentes implémentations de C / C ++ peuvent varier dans ce comportement. Il est possible pour une plate-forme donnée de garantir des assignations atomiques tout en respectant les normes.

Quant à savoir si cela est ou non garanti dans l’ensemble en C / C ++, la réponse est non. Le standard C ne fournit aucune telle garantie. Le seul moyen de garantir une affectation de pointeur est atomique consiste à utiliser un mécanisme spécifique à la plate-forme pour garantir l’atomicité de l’affectation. Par exemple, les méthodes nestedes dans Win32 fourniront cette garantie.

Sur quelle plateforme travaillez-vous?

La réponse à la dérobade est que la spécification C ne nécessite pas qu’une assignation de pointeur soit atomique, vous ne pouvez donc pas compter sur son atomique.

La réponse réelle serait que cela dépend probablement de votre plate-forme, de votre compilateur et éventuellement de l’alignement des écanvass le jour où vous avez écrit le programme.

La modification du pointeur ‘normale’ n’est pas garantie d’être atomique.

Cochez la case ‘Compare and Swap’ (CAS) et d’autres opérations atomiques, pas une norme C, mais la plupart des compilateurs ont un access quelconque aux primitives du processeur. dans le cas de GNU gcc, il existe plusieurs fonctions intégrées

La seule chose garantie par le standard est le type sig_atomic_t.

Comme vous l’avez vu dans les autres réponses, le ciblage de l’architecture générique x86 sera probablement acceptable, mais très risqué avec davantage de matériel “spécialisé”.

Si vous êtes vraiment désespéré, vous pouvez comparer sizeof (sig_atomic_t) à sizeof (int *) et voir en quoi ils sont votre système cible.

C’est une question assez complexe. J’ai posé une question similaire et lu tout ce qui m’a été signalé. J’ai beaucoup appris sur le fonctionnement de la mise en cache dans les architectures modernes et je n’ai rien trouvé qui soit définitif. Comme d’autres l’ont dit, si la largeur du bus est inférieure à la largeur en bits du pointeur, vous risquez d’avoir des problèmes. Spécifiquement si les données tombent à travers une limite de ligne de cache.

Une architecture prudente utilisera un verrou.