10
votes

Modèle de mémoire .NET, Variables volatiles et Test-and-Set: Qu'est-ce qui est garanti?

Je sais que le modèle de mémoire .NET (sur la framework .NET; non compact / micro / silverlight / mono / xna / what-a-vous-avez-vous) garantit que certains types (les entiers et références primitives et les références) étaient Garanti d'être atomique.

En outre, je crois que l'instruction de test X86 / x64 (et interlocked.careeexchange ) références réellement l'emplacement de la mémoire globale, donc si elle réussit un autre Interlocked.careeexchange verrait la nouvelle valeur.

Enfin, je pense que le mot clé volatile est une instruction au compilateur à propager lit et écrit dès que possible et ne pas réorganiser les opérations concernant cette variable (non?).

Ceci conduit à quelques questions:

  1. sont mes croyances ci-dessus correctes?
  2. interlocked.Lead n'a pas de surcharge pour INT, uniquement pour les longs (qui sont 2 mots et ne sont donc normalement pas lus atomiquement). J'ai toujours supposé que le modèle de mémoire .NET garantissait que la valeur la plus récente serait vue lors de la lecture d'INT / références, cependant avec des caches de processeur, des registres, etc. Je commence à voir que cela peut ne pas être possible. Il y a donc un moyen de forcer la variable à être re-récupérée?
  3. est suffisamment volatil pour résoudre le problème ci-dessus pour les entiers et les références?
  4. sur x86 / x64 Puis-je supposer que ...

    S'il y a deux variables entières globales x et Y, les deux initialisées à 0 que si j'écris: xxx

    qu'aucun thread ne verra x = 0 et y = 2 (c'est-à-dire que les écritures se produiront dans l'ordre). Cela change-t-il si elles sont volatiles?


0 commentaires

3 Réponses :


0
votes

Non, le mot clé volatile et la garantie d'atomicité sont beaucoup trop faibles. Vous avez besoin d'une barrière de mémoire pour vous assurer que. Vous pouvez obtenir un explicitement avec la méthode thread.memorybarrier ().


4 commentaires

Ok ... cette réponse 2 et 3, mais qu'en est-il de # 4 (ordre dans lequel les threads verront des données)?


Aussi de: msdn.microsoft.com/en-us /Library/x13tttww7%28vs.71%29.aspx (URL LOL MSDN): "Le système lit toujours la valeur actuelle d'un objet volatil au point requis, même si l'instruction précédente a demandé une valeur du même objet. En outre, la valeur de l'objet est écrite immédiatement à l'affectation. Le modificateur volatil est généralement utilisé pour un champ accessible par plusieurs threads sans utiliser l'instruction de verrouillage pour sérialiser l'accès. L'utilisation du modificateur volatil garantit qu'un thread récupère la valeur la plus récente écrite par un autre fil. "


OH et le code d'exemple dans msdn.microsoft.com/ EN-US / Bibliothèque / AA645755% 28VS.71% 29.aspx - Cela semble contredire votre réponse.


L'article est faux. Vous ne me croirez pas, essayez-le pour vous-même.



6
votes

2 commentaires

Le problème avec la liaison à "C mythes clés dissipés" dans quelque chose à propos de .NET est qu'une source majeure de mythes sur volatile est des personnes qui font la même chose en C, C # et Java. En C # volatile a en effet une certaine sémantique de commande selon msdn.microsoft.com/en-us/library/aa645755%28v=vs.71%29.aspx .


"Le fil pourrait en fait voir x = 0 et y = 2" - car .NET 2.0 Les opérations d'écriture ne peuvent pas être réorganisées.



2
votes

est tombé sur ce vieux fil. Les réponses de HANS et WJ32 sont toutes correctes, à l'exception de la pièce concernant volatile .

spécifiquement concernant votre question

sur x86 / x64 Puis-je supposer que ... si Il y a deux variables globales entière x et y, les deux initialisés à 0 que si si J'écris: x = 1; y = 2;

qu'aucun fil ne verra x = 0 et y = 2 (c'est-à-dire que les écritures seront se produire dans l'ordre). Cela change-t-il si ils sont volatils?

si y est volatile, l'écriture sur x est garantie avant que l'écriture sur y , donc aucun fil ne verra jamais < Code> x = 0 et y = 2 . En effet, l'écriture à une variable volatille a la "version sémantique" (logiquement équivalente à l'émission d'une clôture de libération), c'est-à-dire toutes les instructions de lecture / écriture avant qu'il ne se déplace pas. (Cela implique que si x est volatile, mais y n'est pas, vous pouvez toujours voir le x = 0 et y = 2 .) Voir l'exemple de description et de code dans le C # SPEC pour plus de détails.


0 commentaires