Le C++ Lit et Écrit d'un int Atomique?
J'ai deux fils, l'un mise à jour d'un int et un de le lire. C'est une valeur statistique où l'ordre des lectures et des écritures n'est pas pertinent.
Ma question est, dois-je synchroniser l'accès à cette multi-octets de la valeur de toute façon? Ou, autrement dit, une partie de l'écriture complète et être interrompue, et puis la lecture se produire.
Par exemple, pensez à une valeur = 0x0000FFFF qui est incrémenté de la valeur de 0x00010000.
Est-il un temps où la valeur ressemble 0x0001FFFF que je devrais m'inquiéter? Certainement le plus grand que le type, le plus possible quelque chose comme cela se produise.
J'ai toujours synchronisé de ces types d'accès, mais il était curieux de savoir ce que la communauté pense.
- Vraiment? Je ne ferais pas attention à ce que la communauté de pensée. Je voudrais de soins de ce que sont les faits 🙂
- Lecture intéressante sur le sujet: channel9.msdn.com/Shows/Going+Deep/...
- Spécifiquement pour
=
: stackoverflow.com/questions/8290768/...
Vous devez vous connecter pour publier un commentaire.
Au premier abord, on pourrait penser que les lectures et les écritures de la patrie, de la taille de la machine sont atomiques, mais il y a un certain nombre de questions à traiter, y compris de cohérence de cache entre les processeurs/cœurs. Utilisation des opérations atomiques comme Interloqué* sur Windows et l'équivalent sur Linux. C++0x aura un "atomique" modèle de les emballer dans un joli et croix-plate-forme de l'interface. Pour l'instant, si vous utilisez une plate-forme de la couche d'abstraction, il peut fournir ces fonctions. ACE fait, de voir le modèle de classe ACE_Atomic_Op.
Garçon, quelle question. La réponse est:
Il s'agit de l'architecture du système. Sur un IA32 correctement aligné adresse sera une opération atomique. Non alignés écrit peut être atomique, il dépend de la mise en cache du système en cours d'utilisation. Si la mémoire se trouve à l'intérieur d'une seule ligne de cache L1, alors il est atomique, sinon il ne l'est pas. La largeur du bus entre le CPU et la RAM peut affecter la nature atomique: un alignées correctement 16bit écrire sur un 8086 a été atomique alors que la même écrire sur un 8088 n'était pas parce que le 8088 seulement eu un 8 bits de bus alors que le 8086 eu un 16 bits de bus.
Aussi, si vous êtes à l'aide de C/C++ ne pas oublier de marquer la valeur partagée comme volatile, sinon l'optimiseur pense que la variable n'est jamais mis à jour dans l'un de vos fils.
SI vous êtes à la lecture/écriture de valeur de 4 octets ET il est DWORD alignées en mémoire ET que vous êtes en cours d'exécution sur le I32 architecture, les lectures et les écritures sont atomiques.
Oui, vous avez besoin de synchroniser les accès. Dans C++0x, il sera de données de course, et un comportement indéterminé. Avec les threads POSIX c'est déjà un comportement indéterminé.
Dans la pratique, vous pourriez avoir de mauvaises valeurs si le type de données est plus grand que le natif de la taille de mot. Aussi, un autre thread pourrait ne jamais voir la valeur écrite grâce à l'optimisation de déplacer le lire et/ou écrire.
Vous devez synchroniser, mais sur certaines architectures, il existe des moyens efficaces pour le faire.
Le mieux est d'utiliser des sous-programmes (peut-être masquée derrière des macros), de sorte que vous pouvez conditionnellement remplacer les implémentations avec plate-forme spécifiques.
Le noyau Linux a déjà une partie de ce code.
Sur Windows, Interloqué***Échange***Ajouter, c'est la garantie d'être atomique.
Faire écho à ce que tout le monde dit a l'étage, la langue pré-C++0x ne pouvons rien garantir, à propos de la mémoire partagée de l'accès à partir de plusieurs threads. Toutes les garanties serait pour le compilateur.
Non, ils ne sont pas (ou, au moins, vous ne pouvez pas supposer qu'ils sont). Cela dit, il y a quelques astuces pour le faire de façon atomique, mais ils ne sont généralement pas portable (voir Compare-and-swap).
Je suis d'accord avec beaucoup de et surtout Jason. Sur windows, on pourrait probablement utiliser InterlockedAdd et de ses amis.
Asside à partir du cache problème mentionné ci-dessus...
Si vous port le code pour un processeur avec un petit registre de la taille, il ne sera pas atomique plus.
De l'OMI, problèmes de threading sont trop épineuse pour le risque.
Permet de prendre cet exemple
La première instruction est supposé être atomique, car il se traduit par un unique INC assemblée directive qui prend un seul cycle du PROCESSEUR. Cependant, la deuxième tâche nécessite plusieurs opérations, donc c'est clairement pas une opération atomique.
Un autre message.g,
Encore une fois, vous devez démonter le code pour voir ce qui se passe exactement ici.
x+=6
.tc,
Je pense que le moment où vous utilisez une constante ( 6) , l'instruction ne serait pas achevée dans un cycle de la machine.
Essayez de voir le jeu d'instructions de x+=6 par rapport à x++
Certaines personnes pensent que c ++est atomique, mais ils ont un œil sur l'assemblée généré. Par exemple avec "gcc -S' :
Pour incrémenter un int, le compilateur d'abord le charger dans un registre, et les stocke dans le mémoire. Ce n'est pas atomique.
Définitivement NON !
La réponse de notre plus haute C++ autorité, M. Boost:
Opérations sur "ordinaire", les variables ne sont pas garantis pour être atomique.
arithmetic
opération qui consiste en une lecture-mise à jour-écriture de la séquence sur "ordinaires" variables ne sont pas atomiques, pas de savoir siread
ouwrite
opération sur l '"ordinaire" variables sont atomiques ou pas.Le seul portable est d'utiliser le sig_atomic_t type défini dans le signal.h en-tête de votre compilateur. Dans la plupart des C et C++ implémentations, qui est un int. Ensuite déclarer votre variable comme "volatile sig_atomic_t."