8
votes

Y a-t-il un avantage d'utiliser des mots-clés volatils contrairement à utiliser la classe verrouillée?

En d'autres termes, puis-je faire quelque chose avec une variable volatile qui ne pouvait pas également être résolue avec une variable normale et la classe verrouillée?


1 commentaires

Je sais quel volatile est bon pour. La question est de savoir s'il y a une situation où vous ne pouvez pas remplacer volatile avec une méthode verrouillée?


5 Réponses :


0
votes

Oui, vous pouvez regarder la valeur directement.

Tant que vous n'utilisez la classe verrouillée que pour accéder à la variable, alors il n'y a pas de différence. Ce que volatiles em> est-il indique au compilateur que la variable est spéciale et si elle optimise ne devrait pas supposer que la valeur n'a pas changé. P>

prend cette boucle: p >

bool done = false;

...

while(!done)
{
... do stuff which the compiler can prove doesn't touch done...
}


2 commentaires

Vous pouvez faire la même chose avec verrouillé.Lead ().


Votre description de volatile est légèrement fausse. Vous décrivez C ++ volatile (pas de bien pour la multithreading). C # (et Java) Volatile Créez le compilateur Insérer des opérations de synchronisation lors de l'accès à la variable. En raison de la synchronisation, il est forcé de relire la variable à chaque fois, ce qui a un effet similaire à la volatilité C ++.



17
votes

éditer: Question largement réécrit em>

Pour répondre à cette question, j'ai divisé un peu plus loin dans la matière et j'ai découvert quelques choses sur volatile code> et Imbriqué code> que je n'étais pas au courant. Clarifions cela, non seulement pour moi, mais pour cette discussion et d'autres personnes qui lisent sur ceci: p>

  • volatile code> lecture / écriture est censé être à l'abri de la réorganisation. Ceci seulement em> signifie la lecture et l'écriture, il est pas em> nuire à toute autre action; li>
  • volatilité em> n'est pas forcé sur la CPU, c'est-à-dire que le niveau de matériel (X86 utilise des clôtures d'acquisition et de libération sur tout em> lecture / écriture). Il empêche les optimisations du compilateur ou du CLR; Li>
  • interclocké code> utilise des instructions d'assemblage atomique pour comparaisonxchange ( cmPxchg code>), incrément ( inc code>) etc; li>
  • interclocké code> utilise-t-il parfois un verrou ": a verrouillage du matériel sur les systèmes multi-processeurs ; Dans les systèmes UNI-processeur, il n'y a pas de verrouillage matériel; li>
  • interclocké code> est différent de volatile code> en ce qu'elle utilise une clôture totale em>, où volatile utilise une demi-clôture. LI>
  • Une lecture après une écriture peut être réorganisée lorsque vous utilisez volatile code>. Cela ne peut pas arriver avec interclocké code>. volatileread code> et volatilwrite code> avoir le même problème de réorganisation comme `volatile (lien grâce à Brian Gideon). Li> ul>

    Maintenant que nous avons les règles, nous pouvons définir une réponse à votre question: p>

    • Techniquement: Oui, il y a des choses que vous pouvez faire avec volatile code> que vous ne pouvez pas faire avec interclocké code>:
      1. Syntaxe: Vous ne pouvez pas écrire a = b code> où a code> ou b code> est volatile, mais c'est évident; li>
      2. Vous pouvez lire une valeur différente après l'avoir écrite à une variable volatile en raison de la réorganisation. Vous ne pouvez pas faire cela avec interclocké code>. En d'autres termes: vous pouvez être moins em> sûr avec volatile code>, alors vous pouvez être avec interclocké code>. Li>
      3. Performances: volatile code> est plus rapide que interclocké code>. li> ol> li>
      4. sémantiquement: non, car interclocké code> fournit simplement une superset d'opérations et est plus sûr d'utiliser car elle applique une clôture complète. Vous ne pouvez rien faire avec volatile code> que vous ne pouvez pas faire avec interclocké code> et que vous pouvez faire beaucoup em> avec interclocké code> que vous ne pouvez pas faire avec volatile: p>

        static volatile int x = 0;
        x++;                        // non-atomic
        static int y = 0;
        Interlocked.Increment(y);   // atomic
        
      5. Scope: Oui, déclarant une variable volatile code> le rend volatil pour chaque accès. Il est impossible de forcer ce comportement n'importe quel autre moyen, donc volatile code> ne peut pas être remplacé par en verrouillé code>. Ceci est nécessaire dans des scénarios où d'autres bibliothèques, interfaces ou matériels peuvent accéder à votre variable et la mettre à jour à tout moment ou besoin de la version la plus récente. P> Li> ul>

        Si vous me demandiez, ce dernier bit est le besoin réel réel de volatile code> et peut le rendre idéal où deux processus partagent la mémoire et doivent lire ou écrire sans verrouillage. Déclarant une variable comme volatile code> est beaucoup plus sûre dans ce contexte, puis forçant tous les programmeurs à utiliser interclocké code> (que vous ne pouvez pas forcer par le compilateur). P>


        Edit: La citation suivante faisait partie de ma réponse originale, je le laisserai dans; -) em> p>

        une citation du langage de programmation C # em> standard: p>

        pour les champs non volatils, optimisation techniques qui considèrent que la réorganisation Les instructions peuvent conduire à inattendus et des résultats imprévisibles dans programmes multithreads qui accèdent champs sans synchronisation tels que qui fournit par la Lock-énoncé em>. Ces optimisations risquent d'être effectuées par le compilateur, par le système d'exécution, ou par matériel. Pour les champs volatils, Ces optimisations de réorganisation sont restreint: p>

        • une lecture d'un champ volatil est appelé un lecture volatile em> strong>. Une lecture volatile a: acquérir une sémantique »; c'est-à-dire qu'il est garanti de se produire avant tout Références à la mémoire qui se produisent après dans la séquence d'instructions. P> li>

        • Une écriture d'un champ volatil est appelé un écrit volatile em> fort>. UNE L'écriture volatile a "libération sémantique "; c'est-à-dire qu'il est garanti arriver après toutes les références de mémoire avant l'instruction d'écriture dans le Séquence d'instruction. P> LI> ul> blockQuote>

          mise à jour: em> strong> question est en grande partie réécrit, corrigé ma réponse originale et ajouté une "vraie" réponse p> p> p> P>


7 commentaires

La classe verrouillée ne doit pas nécessairement faire beaucoup avec une serrure et elle a (contrairement à la serrure), pas beaucoup de frais généraux attribués à celui-ci - sur la plupart des processeurs, les méthodes verrouillées sont implémentées comme une instruction unique.


Vous êtes correct, merci de pointer dessus. Regardant dans comparaisexchange (pensant qu'il ne serait pas atomique) SSCLI (Source CLI) SSCLI montre qu'il se traduit par une instruction de montage CMPXCHG sur X86 processeurs et cette instruction est - Comme autre chose dans Interlocké - En effet atomique.


Que et d'autres corrections, plus la réécriture sont maintenant dans la réponse :)


Vous avez dit, vous ne pouvez pas appliquer l'accès Threadsafe à une variable sans mot de clé volatile. Mais vous pouvez définir une propriété qui utilise verrouillé.Read () et interclocked.exchange () dans son getter / Setter.


Cela déguisait une variable. Bien sûr, vous pouvez le faire. Mais cela ne change pas le fait que vous ne pouvez pas avoir une variable variable ou un champ de cette façon. Caché derrière une propriété rend le champ moins sujet à une erreur, mais à l'intérieur de la classe et de l'extérieur (briser OO par la réflexion), il est juste accessible, avec une insuffisance de fil et tout. OTOH, il n'est pas possible de donner l'adresse d'une propriété "volatilisée" à une fonction externe (API, matériels, sinon), vous devez remettre l'adresse du champ et aucune manière verrouillée peut aider alors.


Le passage d'une référence d'une variables volatiles perd sa volatilité, le compilateur vous avertira si vous l'essayez. Cependant, votre réponse est très bonne et épuisante :)


D'accord, mais n'est-ce pas un avertissement sur la référence , ce qui signifie que la lecture / écriture de la variable a toujours la même sémantique? Sinon, comment le CLR permettrait-il d'utiliser volatile pour les variables pouvant être écrites par d'autres libs ou même du matériel?



1
votes

C'est un sujet assez complexe. Je trouve ERISEUP pour être l'une des sources les plus définitives et précises pour concepts multithreading dans le cadre .NET qui pourrait aider à répondre à votre question.

Mais, pour résumer rapidement, il y a beaucoup de chevauchement entre le mot-clé volatile et la classe en verrouillée jusqu'à la manière dont ils peuvent être utilisés. Et bien sûr, les deux vont au-delà de ce que vous pouvez faire avec une variable normale.


1 commentaires

Très bon article! Il faudra un certain temps pour le lire et beaucoup plus longtemps pour le comprendre parfaitement



0
votes

Je ne tenterai pas d'être une autorité sur ce sujet, mais je vous recommande vivement de jeter un coup d'œil à Cet article par le Skeet Jon Vanted.

Regardez également la dernière partie de Cette réponse Quels détails Que volatile doit être utilisé pour.


1 commentaires

L'article de Skeet est bon mais couvre simplement les bases. Je sais quel volatile est bon pour, mais la question était de savoir s'il y a une situation où vous ne pouvez pas remplacer volatile avec une méthode verrouillée?



-1
votes

Oui, vous pouvez obtenir des performances en utilisant une variable volatil au lieu d'une serrure.

Serrure est une barrière de mémoire complète qui peut vous donner les mêmes caractéristiques d'une variable volatil ainsi que d'autres. Comme cela a déjà été dit volatiles, il suffit de s'assurer que dans des scénarios multi-threads si une CPU modifie une valeur dans sa ligne de cache, l'autre processeur voit la valeur immédiatement mais ne garantit pas de verrouillage sémantique.

La chose est une serrure est beaucoup plus puissante que volatile et vous devez utiliser volatil lorsque vous pouvez éviter les serrures inutiles.


1 commentaires

Je ne parlais pas de la déclaration de verrouillage, mais de la classe imbriquée, mais oui ce que vous avez dit est vrai