Eu gostaria de codificar um pequeno programa que ilustra visualmente o comportamento da volatile
palavra - chave. Idealmente, deve ser um programa que executa acesso simultâneo a um campo estático não volátil e que obtém um comportamento incorreto por causa disso.
Adicionar a palavra-chave volátil no mesmo programa deve resolver o problema.
Isso eu não consegui alcançar. Mesmo tentando várias vezes, habilitando a otimização, etc., sempre obtenho um comportamento correto sem a palavra-chave 'volátil'.
Você tem alguma ideia sobre esse assunto? Você sabe como simular esse problema em um aplicativo de demonstração simples? Depende de hardware?
Sim, é dependente do hardware (é improvável que você veja o problema sem vários processadores), mas também depende da implementação. As especificações do modelo de memória nas especificações CLR permitem coisas que a implementação do CLR da Microsoft não necessariamente faz.
fonte
Não é realmente uma questão de falha acontecer quando a palavra-chave 'volatile' não é especificada, mais que um erro pode acontecer quando ela não foi especificada. Geralmente você saberá quando este for o caso melhor do que o compilador!
A maneira mais fácil de pensar sobre isso seria que o compilador poderia, se quisesse, embutir certos valores. Ao marcar o valor como volátil, você está dizendo a si mesmo e ao compilador que o valor pode realmente mudar (mesmo que o compilador não pense assim). Isso significa que o compilador não deve valores in-line, manter o cache ou ler o valor antecipadamente (na tentativa de otimizar).
Este comportamento não é realmente a mesma palavra-chave que em C ++.
O MSDN tem uma breve descrição aqui . Aqui está uma postagem talvez mais detalhada sobre os assuntos de Volatilidade, Atomicidade e Intertravamento
fonte
É difícil demonstrar em C #, já que o código é abstraído por uma máquina virtual, portanto, em uma implementação dessa máquina ele funciona corretamente sem voláteis, enquanto pode falhar em outra.
A Wikipedia tem um bom exemplo de como demonstrar isso em C, no entanto.
A mesma coisa poderia acontecer em C # se o compilador JIT decidir que o valor da variável não pode mudar de qualquer maneira e, portanto, cria um código de máquina que nem mesmo o verifica mais. Se agora outro encadeamento estava mudando o valor, seu primeiro encadeamento ainda pode estar preso no loop.
Outro exemplo é Busy Waiting.
Novamente, isso poderia acontecer com C # também, mas depende fortemente da máquina virtual e do compilador JIT (ou interpretador, se não tiver JIT ... em teoria, acho que o MS sempre usa um compilador JIT e também o Mono usa um; mas você pode desativá-lo manualmente).
fonte
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.
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 emvolatile
onde estava meu primeiro instintolock
).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.
fonte
Me deparei com o seguinte texto de Joe Albahari que me ajudou muito.
Peguei um exemplo do texto acima que alterei um pouco, criando um campo estático volátil. Quando você remove a
volatile
palavra-chave, o programa bloqueia indefinidamente. Execute este exemplo no modo Release .fonte