Voilà ma contribution à la compréhension collective de ce comportement ... Ce n'est pas grand chose, juste une démonstration (basée sur la démonstration de xkip) qui montre le comportement d'un volatile vers une mémoire non volatile (par exemple « normal ») int valeur, côte à côte, dans le même programme ... qui est ce que je cherchais quand j'ai trouvé ce fil.
using System;
using System.Threading;
namespace VolatileTest
{
class VolatileTest
{
private volatile int _volatileInt;
public void Run() {
new Thread(delegate() { Thread.Sleep(500); _volatileInt = 1; }).Start();
while (_volatileInt != 1)
; // Do nothing
Console.WriteLine("_volatileInt="+_volatileInt);
}
}
class NormalTest
{
private int _normalInt;
public void Run() {
new Thread(delegate() { Thread.Sleep(500); _normalInt = 1; }).Start();
// NOTE: Program hangs here in Release mode only (not Debug mode).
// See: http://stackoverflow.com/questions/133270/illustrating-usage-of-the-volatile-keyword-in-c-sharp
// for an explanation of why. The short answer is because the
// compiler optimisation caches _normalInt on a register, so
// it never re-reads the value of the _normalInt variable, so
// it never sees the modified value. Ergo: while (true)!!!!
while (_normalInt != 1)
; // Do nothing
Console.WriteLine("_normalInt="+_normalInt);
}
}
class Program
{
static void Main() {
#if DEBUG
Console.WriteLine("You must run this program in Release mode to reproduce the problem!");
#endif
new VolatileTest().Run();
Console.WriteLine("This program will now hang!");
new NormalTest().Run();
}
}
}
Il y a quelques excellentes explications succinctes ci-dessus, ainsi que quelques bonnes références. Merci à tous de m'avoir aider à obtenir ma tête volatile
(au moins assez pour savoir ne pas compter sur volatile
où mon premier instinct était lock
il).
Salutations, et merci pour TOUS les poissons. Keith
PS: Je serais très intéressé par une démonstration de la demande initiale, qui était: « Je voudrais voir un int volatile statique se comporter correctement lorsque un statique int. comporte mal
J'ai essayé et échoué à ce défi. (En fait, j'abandonnèrent assez rapidement ;-). Dans tout ce que j'ai essayé avec vars statique qu'ils se comportent « correctement », peu importe si oui ou non ils sont volatil ... et j'adorerais avoir une explication de POURQUOI c'est le cas, si c'est effectivement le cas ... Est-ce que le compilateur ne cache pas les valeurs des variables statiques dans les registres (c.-à-d. il met en cache une référence à cette adresse de tas à la place)?
Non, ce n'est pas une nouvelle question ... c'est une tentative d'appartenir à la communauté retour à la question d'origine.
Testé sur .NET 4.0, x86 et x64 - peut confirmer que l'exemple est toujours applicable. Merci! :) –
C'est gentil!Je n'ai jamais su que le JIT fait ce genre d'optimisation et que volatile le désactive. – usr
Juste pour être explicite, vous ajoutez le mot clé "volatile" à la déclaration de foo, n'est-ce pas? – JoeCool