Aqui está minha contribuição para a compreensão coletiva deste comportamento ... Não é muito, apenas uma demonstração (baseada na demo do xkip) que mostra o comportamento de um verso volátil com um valor int não volátil (ou seja, "normal") lado a lado -lado, no mesmo programa ... que é o que eu estava procurando quando encontrei este tópico.
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();
}
}
}
Existem algumas explicações sucintas realmente excelentes acima, bem como algumas referências excelentes. Obrigado a todos por me ajudar a colocar minha cabeça ao redor volatile
(pelo menos o suficiente para saber não confiar em volatile
onde estava meu primeiro instinto lock
).
Saúde e obrigado por TODOS os peixes. Keith.
PS: Eu estaria muito interessado em uma demonstração da solicitação original, que era: "Eu gostaria de ver um int estático volátil se comportando corretamente onde um int estático se comporta mal.
Eu tentei e falhei neste desafio. (Na verdade, desisti rapidamente ;-). Em tudo que tentei com vars estáticos, eles se comportaram "corretamente", independentemente de serem ou não voláteis ... e adoraria uma explicação de PORQUE é esse o caso, se de fato for o caso ... Será que o compilador não armazena em cache os valores de vars estáticos em registradores (ou seja, em vez disso, ele armazena em cache uma referência a esse endereço de pilha)?
Não, esta não é uma pergunta nova ... é uma tentativa de trazer a comunidade de volta à pergunta original.