163 votes

Quand utiliser volatile avec 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é?

196voto

John Dibling Points 56814

De courte et de 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 cela, cela et cela pour plus d'informations sur l' volatile

D'autre part, volatile n'ont une utilisation qui pourrait ne pas être si évident. Il peut être utilisé de la même façon, on peut utiliser const 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. 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 rend volatile sont directement applicables au niveau des systèmes de programmation, plutôt que la normale applications au niveau de la programmation.

L'2003 C++ Standard ne veut pas dire qu' 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 sur volatile variables.

[Mise à jour pour le C++11]

Le C++11 Est la Norme maintenant, ne reconnaissez 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épendante. Cependant, la sémantique de l' volatile n'ont toujours pas changé. volatile n'est pas encore un mécanisme de synchronisation. Bjarne Stroustrup dit dans TCPPPL4E:

Ne pas utiliser volatile , sauf dans les bas-niveau du code qui traite directement avec le matériel.

Ne pas assumer volatile a une signification spéciale dans le modèle de mémoire. Il ne fait pas. Il n'est pas, comme dans certains, plus tard pour les langues-un mécanisme de synchronisation. Sto obtenir la synchronisation, utilisez atomic, un mutex, ou un condition_variable.

[/Fin de mise à jour]

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 qu' volatile . Par exemple, dans Windows 2010 (au moins) d'Acquérir et de Libération de la sémantique ne s'appliquent à certaines opérations sur volatile variables. À partir de la MSDN:

Lors de l'optimisation, le compilateur doit maintenir la commande parmi les références la volatilité des objets ainsi que des références à d'autres objets globaux. Dans en particulier,

Une écriture à un objet volatile (écriture volatile) a Communiqué sémantique; une référence à un mondial ou un objet statique qui se produit avant l'écriture d'un volatile objet dans la séquence d'instruction va se produire avant que écriture volatile dans le binaire compilé.

Une lecture d'un volatile objet volatils (lire) a Acquérir sémantique; une référence à un mondial ou un objet statique qui se produit après une lecture de la mémoire volatile dans la séquence d'instruction se fera après que lecture volatile dans le binaire compilé.

31voto

zeuxcg Points 4578

Volatile est parfois utile pour la raison suivante: ce code:

/* global */ bool flag = false;

while (!flag) {}

est optimisée par la gcc pour:

if (!flag) { while (true) {} }

Ce qui est évidemment incorrect si le drapeau 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.

-1voto

richard Points 1651

Vous avez besoin volatils et, éventuellement, de verrouillage.

volatile raconte l'optimiseur que la valeur peut changer de manière asynchrone, donc

volatile bool flag = false;

while (!flag) {
    /*do something*/
}

va lire le 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.

Le 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.)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X