princípio volátil análise aprofundada

1, a introdução de ferramentas (javap)

1, javap, usado principalmente para ajudar os desenvolvedores insights sobre os mecanismos do compilador Java, as principais opções são:

  • código método de decomposição -c, isto é, o método específico de exibir cada código de bytes
  • -public | protect | pacote | exibição privada é usada para especificar o tipo de nível de membros da classe
  • Displays -verbose informações detalhadas ainda
    de entrada: javap -c Test.class
D:\my-workspace\mayun\JUCDemo\out\production\JUCDemo\com\pingan>javap -c  Test.class
Compiled from "Test.java"
public class com.pingan.Test {
  static volatile java.lang.String b;

  public com.pingan.Test();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
       3: getstatic     #3                  // Field b:Ljava/lang/String;
       6: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
       9: return

  static {};
    Code:
       0: ldc           #5                  // String hello
       2: putstatic     #3                  // Field b:Ljava/lang/String;
       5: return

2, volátil

Tipo de modificador voliate é um papel como uma chave de comando é volátil, para garantir que a instrução não será omitido por causa da otimização do compilador.

2.1 características voláteis

  • Conseguir visibilidade: para garantir a visibilidade dos diferentes tópicos das variáveis ​​operacionais, nomeadamente um thread modifica o valor de uma variável, este novo valor para outro segmento é imediatamente visível.
  • Ordenada: a proibição de reordenação de instruções.
  • Atomicidade: volátil garantir que apenas uma única operação atômica, átomos desta operação i ++ não pode ser garantida;
    Aqui Insert Picture Descrição
    Aqui Insert Picture Descrição
    2,2 princípio implementação de volátil
  • Visibilidade variável memória volátil é uma barreira de memória implementação (Memory Barrier).

Da barreira, conhecido como barreira de memória é uma instrução de CPU.
O programa é executado, a fim de melhorar o desempenho da execução de um processador e um reorganiza compilador instruções, a fim JMM para garantir o mesmo resultado em um compilador diferente ea CPU, para proibir um tipo particular de compilador através da inserção de um tipo específico de barreira de memória ordenação e reordenação desanimado processador, inserir uma barreira de memória irá dizer ao compilador e CPU: não importa o que as instruções não pode e essa memória reordenamento instrução barreira.
Aqui Insert Picture Descrição
2.3 aplicação cenário volátil
1, as condições de utilização devem ter o volátil

  • operação de gravação não é dependente do valor atual da variável;
  • Não incluído nas variáveis ​​invariantes com outras variáveis ​​na fórmula;

2, a fim de usar volátil apenas quando o estado é verdadeiramente independente de outros conteúdos dentro do programa.
Modo 1: bandeira estado
pode regulamentar o uso de variáveis voláteis para alcançar apenas usar um sinalizador booleano, porque o conhecimento é um importante one-time eventos ocorreram, tais como: a inicialização ou solicitação de desligamento

volatile boolean shutdownRequested;
......
public void shutdown() { shutdownRequested = true; }
public void doWork() { 
    while (!shutdownRequested) { 
        // do stuff
    }
}

Modo 2: Disposable Segurança lançou
uma falta de sincronização pode levar a não conseguir visibilidade, o que torna determinar quando a escrever uma referência de objeto em vez do valor original torna-se mais difícil, na ausência de sincronização, você pode encontrar uma referência de objeto valor atualizado (escrito por outro thread) e os antigos valores do estado da exist objeto.

public class BackgroundFloobleLoader {
    public volatile Flooble theFlooble;
 
    public void initInBackground() {
        // do lots of stuff
        theFlooble = new Flooble();  // this is the only write to theFlooble
    }
}
 
public class SomeOtherClass {
    public void doWork() {
        while (true) { 
            // do some stuff...
            // use the Flooble, but only if it is ready
            if (floobleLoader.theFlooble != null) 
                doSomething(floobleLoader.theFlooble);
        }
    }
}

Modo Três: observadores independentes
simplesmente outro modo do uso seguro da volátil é publicada regularmente observações para usos internos. Por exemplo: suponha que exista um sensor para sentir o ambiente temperatura ambiente, uma discussão de fundo pode ler uma vez sensor a cada poucos segundos, e atualiza a variável volátil contém o documento atual, em seguida, outros tópicos pode ler as variáveis, portanto, capaz de ver em qualquer momento após o último valor da temperatura.

public class UserManager {
    public volatile String lastUser;
 
    public boolean authenticate(String user, String password) {
        boolean valid = passwordIsValid(user, password);
        if (valid) {
            User u = new User();
            activeUsers.add(u);
            lastUser = user;
        }
        return valid;
    }
}

Modelo 5: barato leitura - estratégia de bloqueio de gravação

  • bastante volátil para realizar a função do contador, que o interior ++ X é na verdade três operações (leitura, add, armazenar) uma combinação simples. Se várias linhas aconteceu durante a tentativa de executar uma operação contra volátil incremental, valor, então ele é atualizado pode ser perdida.
  • Se você ler muito mais do que as operações de gravação, você pode usar o bloqueio interno, e variáveis ​​voláteis para reduzir a sobrecarga de uma combinação caminho de código comum.
  • Sincronizados para garantir o uso seguro da operação contra incremento é atômica, e usar volátil para assegurar a visibilidade dos resultados atuais. Se as palavras de atualização em casos pouco frequentes, os métodos podem ser modificados para melhor desempenho. Por causa da sobrecarga do caminho leitura envolve apenas volátil lê, que normalmente é melhor do que o custo de uma aquisição de bloqueio não competitivo.
@ThreadSafe
public class CheesyCounter {
    // Employs the cheap read-write lock trick
    // All mutative operations MUST be done with the 'this' lock held
    @GuardedBy("this") private volatile int value;
 
    public int getValue() { return value; }
 
    public synchronized int increment() {
        return value++;
    }
}

Modelo 6: verifique
um único caso de um modo de implementação, porque um monte de gente vai ignorar a palavra-chave volátil, não porque a palavra-chave, o programa também pode ser uma boa corrida, mas a estabilidade do código não é sempre 100%, talvez naquela época, o bug escondido para lidar com a tempestade.

class Singleton {
    private volatile static Singleton instance;
    public static Singleton getInstance() {
        if (instance == null) {
            syschronized(Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    } 
}

carregamento lento recomendado escrita elegante:

public class Singleton {
    
   private static class SingletonHolder{
       static  Singleton instance = new Singleton();
   }

   public static  Singleton getInstance(){
       return SingletonHolder.instance;
   }

}

Publicado 21 artigos originais · ganhou elogios 4 · Visualizações 500

Acho que você gosta

Origin blog.csdn.net/weixin_39617728/article/details/105058387
Recomendado
Clasificación