Pergunta

é mencionado no modelo de memória Java que:Quando um thread sai de um bloco sincronizado como parte da liberação do monitor associado, o JMM exige que o cache do processador local seja liberado para a memória principal.De forma similar, como parte da aquisição do monitor ao entrar em um bloco sincronizado, os caches locais são invalidados para que as leituras subsequentes irão diretamente para a memória principal e não para o cache local.

então por que nesse código devo declarar a instância como volátil, já que quando o segundo thread entrar no bloco de sincronização irá diretamente para a memória principal?

public final class MySingleton {
  private static MySingleton instance = null;
  private MySingleton() { } 
  public static MySingleton getInstance() {
    if (instance == null) {
      synchronized (MySingleton.class) {
        if (instance == null) {
          instance = new MySingleton();
        }
      }
    }
    return instance;
  }
}

Quero dizer, quando outro thread entra no bloco de sincronização e faz a segunda verificação, ele deve ser atualizado da memória principal, conforme mencionado.

Foi útil?

Solução

A condição de corrida é esta:

  1. Tópico A vê instance == NULL e está executando este código instance = new MySingleton();.A escrita para instance é visível, mas as gravações em MySingleton ainda não estão.

  2. Tópico B vê instance != NULL e começa a trabalhar na instância.

  3. Thread B agora está trabalhando em um objeto cuja construção ele não pode ver.

Fazendo instance volátil resolve o problema, pois a especificação de memória JDK, a partir do JDK5, garante que as gravações em objetos não voláteis não serão vistas fora de ordem em relação a uma gravação em um objeto volátil.Então, qualquer tópico que vê instance != NULL deve ver a própria instância.

Outras dicas

Você deve declará-lo volátil, caso contrário não há garantia de que duas chamadas para getInstance() retornarão a mesma instância.

Não há garantia de que a memória principal será acessada, apenas um valor consistente com o cache.ou sejatodos os threads verão o mesmo valor.

POR FALAR NISSO:Você sabe, é claro, que é muito mais complexo do que o necessário.Tudo o que você precisa é

public enum MySingleton {
     INSTANCE;
}

faz praticamente a mesma coisa.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top