Quand utiliser volatile avec le multi threading?
Si il y a deux fils de l'accès à une variable globale, puis de nombreux tutoriels dire que la variable volatile pour empêcher le compilateur de la mise en cache de la variable dans un registre et ainsi de ne pas obtenir mis à jour correctement.
Cependant les deux fils à la fois de l'accès à une variable partagée est quelque chose qui demande de protection par l'intermédiaire d'un mutex n'est-ce pas?
Mais dans ce cas, entre le fil de verrouillage et de libérer le mutex le code est dans une section critique où seulement qu'un thread peut accéder à la variable, auquel cas la variable n'a pas besoin d'être volatile?
Donc qu'est-ce que l'utilisation et le but de volatiles dans un programme multi-threadé?
- Dans certains cas, vous ne voulez pas/besoin d'une protection par le mutex.
- Parfois, c'est bien d'avoir une condition de concurrence, parfois il ne l'est pas. Comment êtes-vous à l'aide de cette variable?
- Un exemple de cas où il est "amende" pour avoir une course de, s'il vous plaît?
- Va ici. Imaginez que vous avez un thread de travail qui est le traitement d'un certain nombre de tâches. Le thread de travail incrémente un compteur à chaque fois qu'il termine une tâche. Le maître thread lit régulièrement ce compteur et les mises à jour de l'utilisateur avec des nouvelles de l'avancement. Tant que le compteur est bien aligné pour éviter de déchirer il n'est pas nécessaire de synchroniser les accès. Bien qu'il y a une course, c'est bénin.
- Il serait difficile d'en évaluer la sécurité d'un tel dispositif sans un examen complet de la code. Même si un examen a conclu que les écritures ont été atomique (douteuse) et entièrement écrit-via le cache (difficile à dire), je serais encore à rejeter ce que les "mauvais code". C'est safetey serait extrêmement ténue, et facilement brisée par la plus petite des modifications au code. Maintennance les programmeurs de briser cet appareil facilement, et les problèmes qui n'apparaissent pas dans les tests.
- Le matériel sur lequel l'exécution de ce code garantit que alignés variables ne peuvent souffrir de la déchirure. Si le travailleur est à la mise à jour de n à n+1 que le lecteur lit, le lecteur ne se soucie pas de savoir si ils obtiennent n ou n+1. Pas de décisions importantes vont être prises, car il est uniquement utilisé pour la production de rapports d'avancement.
- Je suppose que je ne sais pas ce que tu veux dire par "la déchirure."
- re déchirure, je vous offre la suite de Joe Duffy: msdn.microsoft.com/en-us/magazine/cc817398.aspx
- Wow, mur de texte. 🙂 Mais merci, je n'ai pas lu encore. Je le ferai quand je reçois une chance.
- C'est toutes d'excellentes choses, mais le peu sur déchirement est seulement un ou deux paragraphes.
- Get +23 question score, accepter -18 réponse. F**k la logique.
- isvolatileusefulwiththreads.com (ou @DavidHeffernan, software.intel.com/en-us/blogs/2013/01/06/... est à lire absolument morceau sur "bénigne" données courses)
- Quand utiliser: jamais.
- par exemple, si c'est "bien" d'avoir une course" à Chaque fois que c'est bien d'utiliser un mutex. Ou atomique. À peu près tous les non trivial MT programmes inoffensifs conditions de course.
Vous devez vous connecter pour publier un commentaire.
Court & réponse rapide:
volatile
est (presque) inutile pour la plate-forme agnostique, multithread de programmation d'application. Il ne fournit pas de synchronisation, il ne crée pas de la mémoire des clôtures, ni n'assure la commande de l'exécution des opérations. Il n'a pas à effectuer des opérations atomiques. Il n'est pas de rendre votre code comme par magie thread-safe.volatile
peut-être le plus mal compris de la facilité dans l'ensemble de C++. Voir cette, cette et cette pour plus d'informations survolatile
D'autre part,
volatile
a quelques utilisation qui pourrait ne pas être si évident. Il peut être utilisé de la même façon, on pourrait utiliserconst
pour aider le compilateur vous montrer où vous pouvez faire une erreur dans l'accès à certaines ressources partagées dans un non-protégés façon. Cette utilisation est discutée par Alexandrescu dans cet article. Toutefois, c'est essentiellement l'aide de C++ type de système d'une manière qui est souvent considéré comme une machination et peut évoquer un Comportement Indéfini.volatile
a été spécifiquement conçu pour être utilisé lors de l'interfaçage avec le matériel mappé en mémoire, les gestionnaires de signaux et le setjmp code machine instruction. Cela rendvolatile
directement applicables au niveau des systèmes de programmation, plutôt que la normale applications au niveau de la programmation.2003 de la Norme C++ ne permet pas de dire que
volatile
s'applique à tout type d'Acquérir ou de Libération de la sémantique sur les variables. En fait, la Norme est complètement silencieux sur toutes les questions de multithreading. Toutefois, les plates-formes spécifiques ne s'appliquent Acquérir et la Libération de la sémantique survolatile
variables.[Mise à jour pour le C++11]
Le C++11 Est la Norme maintenant ne reconnaître le multithreading directement dans le modèle de mémoire et de la lanuage, et il offre des installations de bibliothèque de traiter avec elle en une plate-forme indépendant de la manière. Cependant, la sémantique de
volatile
n'ont toujours pas changé.volatile
est pas encore un mécanisme de synchronisation. Bjarne Stroustrup dit dans TCPPPL4E:[/Mise à jour de fin]
Ci-dessus s'applique le C++ le langage lui-même, tel que défini par le Standard 2003 (et maintenant le 2011 Standard). Certains des plates-formes spécifiques, toutefois, ne l'ajout de fonctionnalités supplémentaires ou des restrictions à ce
volatile
n'. Par exemple, dans MSVC 2010 (au moins) d'Acquérir et de Libération de la sémantique ne s'appliquent à certaines opérations survolatile
variables. À partir de MSDN:Cependant, vous pourriez prendre note du fait que si vous suivez le lien ci-dessus, il y a un débat dans les commentaires quant à savoir si ou de ne pas acquérir/libération de la sémantique fait s'appliquent dans ce cas.
volatile
ne doit pas être confondu entre les langues, y compris ce qui pourrait être trouvé dans un dictionnaire 🙂 (Il est très stricte de la mémoire sémantique de modèle en Java, par exemple, mais c'est un différentes langage/environnement).volatile
c'est parce que vous juché sur les épaules de ceux qui ont utilisé lavolatile
à mettre en œuvre des bibliothèques de threading.volatile
qui est probablement correcte pour la plupart des gens qui écrivent niveau de l'application du code.volatile
en fait ne en C++. Ce que @John a dit est correct à la fin de l'histoire. Il n'a rien à voir avec le code de l'application vs code de bibliothèque, ou "ordinaire" vs "comme dieu omniscient programmeurs" pour cette question.volatile
est inutile et inutile pour la synchronisation entre les threads. Le filetage des bibliothèques ne peut pas être mis en œuvre en termes devolatile
; il doit s'appuyer sur une plate-forme spécifique de détails, de toute façon, et quand vous comptez sur ceux-ci, vous n'avez plus besoinvolatile
.volatile
est un langage C++ concept, pas une mise en œuvre du concept. Pourtant, vous avez dit que c'était utile, car certains détails de mise en œuvre. Qui n'a pas d'incidence sur son utilité en C++.volatile
est version&acquérir [sémantique sur Visual C++ ](msdn.microsoft.com/en-us/library/12a04hfd%28v=vs.80%29.aspx) (voir aussi ma réponse ici: stackoverflow.com/questions/6995310/...)std::atomic<T>
Volatile est parfois utile pour la raison suivante: ce code:
est optimisée par la gcc pour:
Qui est manifestement inexact si l'indicateur est écrit par l'autre thread. Notez que sans cette optimisation du mécanisme de synchronisation fonctionne probablement (selon le code des autres certaines barrières de la mémoire peuvent être nécessaires) - il n'est pas nécessaire pour un mutex dans 1 producteur - 1 consommateur scénario.
Sinon le mot clé volatile est trop bizarre pour être utilisable - il ne fournit pas de mémoire garanties de classement wrt à la fois volatile et non volatile accès et de ne pas fournir toutes les opérations atomiques - c'est à dire que vous n'obtenez pas l'aide du compilateur avec mot-clé volatile sauf désactivé registre de la mise en cache.
volatile
n'empêche pas l'accès à la mémoire de réorganisation.volatile
accède à ne pas être réorganisées à l'égard des uns et des autres, mais ils fournissent aucun garantie au sujet de la réorganisation à l'égard de non-volatile
objets, et ainsi, ils sont fondamentalement inutile que les drapeaux ainsi.while (!global_flag) { sleep(1); }
fonctionne sansvolatile
parce que leurs compilateurs ne pas regarder danssleep()
lors de l'optimisation et donc supposer quesleep()
peut modifierglobal_flag
et donc le bon code est produit pour les mauvaises raisons. Peut-être un exemple pertinent pourrait être construit avec LLVM lien-temps optimisations?volatile
.while (work_left) { do_piece_of_work(); if (cancel) break;}
, si l'annulation est réorganisée au sein de la boucle, la logique est toujours valide. J'avais un morceau de code qui fonctionnait de la même façon: si le thread principal veut mettre fin, il définit l'indicateur pour les autres threads, mais il n'est pas...volatile
ainsi qu'un compilateur serait libre pour optimiser un délimitée nombre de tentatives d'accès [par exemple, si un compilateur se déroule une boucle de 8 fois, il aurait seulement pour vérifier la variable une fois dans le déroulé de la boucle, plutôt que de vérifier huit fois]. La surcharge imposée par un mécanisme de relâchement de la sémantique...Vous avez besoin volatils et, éventuellement, de verrouillage.
volatils raconte l'optimiseur que la valeur peut changer de manière asynchrone, donc
va lire drapeau à chaque fois autour de la boucle.
Si vous activez l'optimisation off ou faire de chaque variable volatile d'un programme se comporte de la même, mais plus lent. volatile signifie simplement " je sais que vous venez juste de le lire et de savoir ce qu'il dit, mais si je dis le lire, puis de le lire.
De verrouillage est une partie du programme. Donc ,en passant, si vous êtes à la mise en œuvre de sémaphores puis, entre autres choses, ils doivent être volatile. (N'essayez pas, c'est difficile, aura probablement besoin d'un peu d'assembleur ou le nouveau atomique choses, et ça a déjà été fait.)
volatile
n'est pas vraiment utile, même dans ce cas. Mais occupé attente est parfois utile de la technique.volatile
empêcher CPU réorganisation et sur la plupart des plateformes modernes, il n'est pas réellement le faire.volatile
? Avez-vous une Norme autre que ces personnes? stackoverflow.com/questions/2535148/...volatile
s émettant des barrières de la mémoire, de sorte que la réorganisation est pas empêché.volatile
, qui est la garantie de ne pas se produire - pas de réorganisation de tout dit en lecture/écriture par rapport à d'autres états (si oui ou non ils sont égalementvolatile
), qui est autorisé à se produire. Est ce que tu veux dire?volatile
variables ne pas émettent les barrières de la mémoire, même sur les plates-formes qui en ont besoin pour prévenir les lectures et les écritures de réorganisation et/ou fusionné. Essayez-la. (Êtes-vous d'accord que le CPU peut fusionner écrit à la mémoire ordinaire? Voyez-vous le compilateur fait rien pour l'arrêter quand deux écritures se produisent à la mêmevolatile
? Qu'en est écrit à deux adjacentsvolatile short
s, ou d'un "ABA" écrire pour eux? Voyez-vous quelque chose émis pour arrêter la combinaison d'écriture?)i=1; j=2; k=3;
et le CPU nei=1; k=3;
en une seule opération atomique. Rien n'empêche un CPU en faisant cela, même sii
,j
, etk
sontvolatile
et réel Processeurs faire. De processeurs peut même optimiser hors écrit àvolatile
s du monde réel et les Processeurs de faire ça. Donci=1; j=2; i=3;
peut entraîner lai=1;
écrire arriver optimisé, encore une fois, même sii
estvolatile
. C'est pourquoi de nombreux Processeurs ont de la mémoire de la barrière des opérations etvolatile
ne les utilise pas, ni est-il tenu de le faire.i=1; j=2; i=3;
est transformé enj=2; i=3;
qui briserait un autre thread attend (à tort) quej==2
ne peut se faire que sii>0
.Une fois un intervieweur qui croyait également que la volatilité est inutile d'argumenter avec moi que l'Optimisation ne cause pas de questions et se référant à différents cœurs à la séparation des lignes de cache et de tout ce qui (ne comprenais pas vraiment ce qu'il était exactement se référant à l'). Mais ce morceau de code lors de la compilation avec-O3 sur g++ g++ -O3 thread.cpp -lpthread), il montre un comportement indéterminé. En gros, si la valeur est avant tout vérifier qu'il fonctionne bien et si pas, il va dans une boucle sans prendre la peine d'aller chercher la valeur (ce qui a réellement changé par l'autre thread). Fondamentalement, je crois que la valeur de checkValue n'obtient récupérée à la fois dans le registre et n'est jamais vérifié de nouveau sous le plus haut niveau de l'optimisation. Si sa valeur true avant de le chercher, il fonctionne très bien et si pas, il va dans une boucle. S'il vous plaît corrigez-moi si me trompe.
volatile
? Oui, ce code est UB-mais c'est UB avecvolatile
ainsi.