Quelque part, j'ai lu que les opérateurs unaires sont par nature atomiques et peuvent donc être utilisés tels quels dans un environnement multi-thread. Pour confirmer la même chose, j’ai écrit deux programmes distincts où
J'ai comparé le désassemblage des deux programmes et n'ai trouvé aucune différence. S'il vous plaît fournir vos contributions à ce sujet.
Quelque part, j'ai lu que les opérateurs unaires sont par nature atomiques et peuvent donc être utilisés tels quels dans un environnement multi-thread.
Cette source est complètement fausse. Vous devez utiliser std::atomic
(ou l'équivalent C) pour obtenir l'atomicité - les opérations unaires ne sont pas spéciales.
J'ai comparé le désassemblage des deux programmes et n'ai trouvé aucune différence
Cela ne signifie pas que les opérations générées sont atomiques. Il n'y a pas de différence, car tout compilateur décent optimisera x=x+1
et ++x
dans le même assemblage (en supposant les types intégrés).
Lorsque vous écrivez en C++ multiplateforme, vous n’avez que le comportement atomique lorsque vous utilisez std::atomic<>
.
Il est vrai que sur certaines plates-formes, comme Intel 64 bits, le processeur garantit que inc
est atomique. Cependant, veuillez ne pas écrire de code qui en dépend! En tant que futur débogueur, je voudrais savoir quelles données sont destinées à être partagées via des threads et lesquelles ne le sont pas.
Utiliser std::atomic<int>
pourrait être un peu plus de travail à écrire, cependant, cela garantit que tout se comporte de manière atomique (sur chaque plate-forme) en revenant aux exigences de la plate-forme ( std :: atomic :: is_lock_free ) ou explicitement mettre un verrou autour de l'accès. Il insère également des gardes afin de s’assurer que les caches des autres cœurs de processeur sont invalidés (si la plate-forme le requiert).
En pratique pour Intel 64 bits, cela devrait vous donner le même assemblage, sinon, notez un bogue sur votre compilateur.
En même temps, certaines opérations avec ints peuvent ne pas être atomiques (opérateur * =), std::atomic
ne les tient tout simplement pas, vous obligeant à les utiliser correctement.
Remarque: ++x
et x = x+1
sont des opérations différentes, elles peuvent être optimisées pour le même assemblage. Compte tenu des exigences de la plate-forme non atomique, le second problème est soudain un bogue qui prend des jours à résoudre.
L'affirmation selon laquelle un opérateur unaire est nécessairement atomique est un mythe.
Par exemple, ++x
requiert une lecture et une écriture dans x
pour que le risque d’une course de données s’ouvre.
Le fait que ++x
soit compilé dans le même code que x = x + 1
n'est pas pertinent.
Si vous souhaitez éviter les courses de données, utilisez des types atomiques ou des unités d'exclusion mutuelles si un type atomique approprié n'est pas disponible. Pour éviter tout doute, int
n'est pas nécessairement un type atomique.
Quelque part, j’ai lu que les opérateurs unaires sont de nature atomique, et donc ils peut être utilisé tel quel dans un environnement multi-threadé.
C'est faux. x++
, par exemple, nécessite une charge de x
, un add et un magasin de x
. Ces instructions ne sont pas atomiques par nature.
Pas vrai. Même si c'était le cas, quelle raison https://en.cppreference.com/w/cpp/atomic/atomic#Type_aliases a alors?
Je pense que ce qu’ils voulaient dire, c’est probablement qu’un calcul sur une telle opération est généralement très minutieux et qu’il est donc fort probable qu’il n’ya jamais de situation de concurrence critique, ce qui est généralement vrai dans le code live, dans lequel vous ne calculez pas simultanément x ++ sur 4 pour des boucles.
Vous n'avez pas spécifié le type de x.
Le caractère atomique de l'opération dépend du système cible. Une opération unaire peut ne pas être atomique sur les systèmes RMW tels que les micro contrôleurs RISC.
Il n'y a pas de réponse générique unique à cette question.
Vous faites une hypothèse sur le code généré, si une seule instruction est générée, oui, ce sera atomique, sinon non.
Dans votre cas, cela suppose que le processeur cible ait l'instruction inc <address>
et que le compilateur la produise.
Comportement atomique des opérateurs unaires
En C, les __/__ correctifs ++
ne sont pas unary-operators tels que & * + - ~ !
. mais fait partie d'une expression unaire . Donc, le titre de la question est incompatible avec le corps.
Même un opérateur unaire tel que +
n'est pas atomique, car l'accès à l'objet (pensez long long
) permet d'effectuer plusieurs lectures de code op.