En général, pour int num
, num++
(o ++num
), comme une opération de lecture-modification-écriture, est non atomique . Mais je vois souvent des compilateurs, par exemple CCG et génère le code suivant ( essayez ici ):
void f()
{
int num = 0;
num++;
}
f():
push rbp
mov rbp, rsp
mov DWORD PTR [rbp-4], 0
add DWORD PTR [rbp-4], 1
nop
pop rbp
ret
Depuis la ligne 5, qui correspond à num++
est une instruction, peut-on conclure que num++
est atomique dans cette affaire ?
Et si oui, cela veut-il dire que les produits ainsi générés num++
peut être utilisé dans des scénarios concurrents (multithreads) sans risque de course aux données (c'est-à-dire que nous n'avons pas besoin de le fabriquer, par exemple, std::atomic<int>
et imposer les coûts associés, puisque c'est de toute façon atomique) ?
UPDATE
Remarquez que cette question est pas si l'incrémentation es atomique (ce n'est pas le cas et c'était et c'est toujours la première ligne de la question). Il s'agit de savoir si elle puede dans des scénarios particuliers, c'est-à-dire si la nature d'une seule instruction peut, dans certains cas, être exploitée pour éviter l'overhead de l'algorithme d'analyse de l'information. lock
préfixe. Et, comme le mentionne la réponse acceptée dans la section sur les machines uniprocesseur, ainsi que cette réponse , la conversation dans ses commentaires et d'autres expliquent, il peut (mais pas avec C ou C++).
68 votes
Qui vous a dit que
add
est atomique ?6 votes
Étant donné que l'une des caractéristiques de l'atomique est la prévention de types spécifiques de réordonnancement pendant l'optimisation, non, indépendamment de l'atomicité de l'opération réelle
1 votes
Il se peut que votre compilateur voit que num++ peut être optimisé à cela parce que vous n'utilisez pas la valeur de retour de num++.
2 votes
Il doit encore charger num, l'augmenter puis le réécrire en mémoire
20 votes
Je tiens également à souligner que si ce qui est atomique sur votre plateforme, il n'y a aucune garantie qu'il le sera sur une autre pltaforme. Soyez indépendant de la plateforme et exprimez votre intention en utilisant un fichier de type
std::atomic<int>
.9 votes
Pendant l'exécution de cette
add
un autre noyau pourrait voler cette adresse mémoire dans le cache de ce noyau et la modifier. Sur un processeur x86, leadd
l'enseignement a besoin d'unelock
préfixe si l'adresse doit être verrouillée dans le cache pendant la durée de l'opération.21 votes
Il est possible pour cualquier pour que l'opération soit "atomique". Il suffit d'avoir de la chance et de ne jamais exécuter quoi que ce soit qui puisse révéler qu'elle n'est pas atomique. Atomique n'a de valeur que comme garantie . Étant donné que vous regardez le code d'assemblage, la question est de savoir si cette architecture particulière vous fournit la garantie y si le compilateur fournit une garantie que c'est l'implémentation au niveau de l'assemblage qu'ils choisissent.
2 votes
Dans ce cas, votre fonction telle qu'elle est est parfaitement sûre, car les autres threads n'ont aucun moyen d'accéder à la pile de données
num
variable. Mais ce n'est probablement pas ce que vous demandez. (Il serait peut-être préférable que votrenum
étaient une variable globale).0 votes
Donner l'impression de fonctionner est une réponse valable à l'invocation d'un comportement indéfini.
0 votes
@Lmn : Les questions de SO devraient utiliser des blocs de code pour le code, pas des images de texte. La compacité de l'image était agréable, mais il y a suffisamment de raisons de ne pas utiliser d'images pour que vous laissiez la modification de Joseph s'appliquer. (Les utilisateurs aveugles avec des lecteurs d'écran, les pare-feu d'entreprise qui bloquent les images, etc.) Dans d'autres cas, la possibilité pour les moteurs de recherche de rechercher le code est pertinente ; ce n'est pas le cas ici mais les autres raisons sont suffisantes.