Si j'accède à un seul type entier (E.G. Long, Int, Bool, etc.) Dans plusieurs threads, dois-je utiliser un mécanisme de synchronisation tel qu'un mutex pour les verrouiller. Je crois comprendre que comme des types atomiques, je n'ai pas besoin de verrouiller l'accès à un seul fil, mais je vois beaucoup de code là-bas qui utilise un verrouillage. Profilage Ce code montre qu'il existe une performance significative pour utiliser des serrures, donc je préférerais pas. Donc, si l'article que j'accède correspond à une largeur de bus entier (par exemple 4 octets sur un processeur 32 bits) Dois-je verrouiller l'accès à celui-ci lorsqu'il est utilisé sur plusieurs threads? Mettre un autre moyen, si le fil a écrit en integer variable x en même temps que le thread B lisez à partir de la même variable, est-il possible que le fil b pourrait finir de quelques octets de la valeur précédente mélangée à quelques octets de la valeur étant écrite? Cette architecture est-elle dépendante, par exemple OK pour les entiers d'octets de 4 octets sur les systèmes 32 bits mais dangereux sur 8 octets dans des systèmes 64 bits? P>
EDIT: strong> vient de voir cette Poste associé qui aide un peu juste. p>
7 Réponses :
Il n'y a pas de support pour les variables atomiques en C ++, de sorte que vous avez besoin de verrouillage. Sans verrouillage, vous ne pouvez spéculer que quelles instructions exactes seront utilisées pour la manipulation des données et si ces instructions garantiraient un accès atomique - ce n'est pas la manière dont vous développez des logiciels fiables. P>
Je dois être en désaccord (un peu). Il n'y a pas de variables atomiques en C ++, non, mais il n'y a pas de serrure non plus. Dès que vous entrez dans la multiplication multipliée, vous devez compter sur les garanties données par votre compilateur spécifique. Et que i> a beaucoup de garanties d'atomicité. Généralement, les accès aux objets de taille de mots seront atomiques. Bien sûr, la langue C ++ ne garantit pas cela, mais votre compilateur spécifique fait probablement probablement. Bien entendu, le compilateur rend généralement peu de garanties sur la réorganisation, de sorte que vous aurez peut-être encore besoin de verrouillage, ou d'au moins des barrières de mémoire, en fonction de ce que vous faites exactement.
Oui, il serait préférable d'utiliser la synchronisation. Toute données accessible par plusieurs threads doit être synchronisée. p>
Si c'est la plate-forme Windows, vous pouvez également vérifier ici: Accès variable interlocké . P>
Oui. Si vous êtes sur Windows, vous pouvez consulter verrouillé < / a> fonctions / variables et si vous êtes de la persuasion de boost, vous pouvez regarder leur implémentation de variables atomiques . p>
Si Boost est trop lourd, placez-le " Atomic C ++ " dans votre moteur de recherche préféré vous donnera beaucoup de nourriture pour la pensée. P>
Vous ne verrouillez jamais de valeur - vous verrouillez une opération sur une valeur. P>
C & C ++ Ne mentionnez pas explicitement les threads ou les opérations atomiques - de sorte que les opérations qui ressemblent à elles pourraient ou doivent être atomiques - ne sont pas garanties par la spécification de langue d'être atomique. P>
Ce serait certes un compilateur assez déviant qui a géré une lecture non atomique sur un INT: Si vous avez une opération qui lit une valeur - theres probablement pas besoin de le protéger. Cependant, il pourrait être non atomique s'il couvre une limite de mot machine. P>
opérations aussi simples que GCC a des fonctions intrinsèques telles que m_counter ++ code> implique une extraction, une incrément et une opération de stockage - une condition de course: un autre thread peut modifier la valeur après la fetch mais avant le magasin - et donc doit être protégé par Un mutex - ou trouver votre prise en charge de vos compilateurs pour des opérations imbriquées. MSVC a des fonctions telles que _InterlockedinCrement () qui incremportera en toute sécurité un emplacement de mémoire tant que toutes les autres écrivies utilisent de la même manière à la mise à jour de l'emplacement de la mémoire - qui est des commandes de grandeur plus légères que d'invoquer une section même critique. P>
__ sync_add_and_fetch code> qui peut également être utilisée pour effectuer des opérations verrouillées sur des valeurs Word de la machine. P>
Merci pour cela, Interlockedexchange est probablement la fonction que je recherche, car un seul fil écrit réellement à la variable en question, alors que d'autres le lisent simplement.
Dans 99,99% des cas, vous cas au point: j'ai été mordu par une implémentation de verrouillage de spin où déverrouillez simplement l'attribution de zéro à un Voir: P>
Volatile code> Variable entier. Le compilateur était la réorganisation des opérations de déverrouillage avant l'opération réelle sous la serrure, sans surprise, conduisant à des accidents mystérieux. p>
Bug compilateur. La volatile est une limite d'optimisation.
@Joshua, je sens du sarcasme? Sinon, alors non, ce n'est pas un bug de compilateur. Rien n'empêche le compilateur de réorganiser la réorganisation de rouge / écrit non volatile autour des volatiles, il ne peut que réorganiser la réorganisation des lectures volatiles / écrit entre eux. Voir cette question: Stackoverflow.com/questions/2535148/...
Si vous êtes sur une machine avec plus d'un noyau, vous besoin em> faire les choses correctement même si les écrits d'un entier sont atomiques. Les problèmes sont deux fois: p>
Si c'était juste la première chose, vous alliez bien de marquer la variable
volatile code>, mais le second est vraiment le tueur et vous ne vraiment em> voir le différence sur une machine multicœur. Ce qui se trouve être une architecture qui devient beaucoup plus courante qu'elle était ... oups! Il est temps d'arrêter d'être bâclé; Utilisez le code correct mutex (ou synchronisation ou autre) pour votre plate-forme et tous les détails de la façon de faire de la mémoire de travail comme vous le croyez. P>
La multithreading est dure et complexe. Le nombre de problèmes difficiles à diagnostiquer les problèmes qui peuvent contourner est assez grand. En particulier, sur les architectures Intel lit et écrit à partir d'entiers alignés 32 bits est garanti pour être atomique dans le processeur, mais cela ne signifie pas qu'il est prudent de le faire dans des environnements multithreads. p>
Sans gardes corrects, le compilateur et / ou le processeur peuvent réorganiser les instructions de votre bloc de code. Il peut cacher des variables dans des registres et ils ne seront pas visibles dans d'autres threads ... p>
Le verrouillage est coûteux, et il existe différentes implémentations de structures de données sans verrouillage pour optimiser les performances élevées, mais il est difficile de le faire correctement. Et le problème est que les bugs de la concurrence sont généralement obscurs et difficiles à déboguer. P>