Nos programas Java, às vezes pode ser necessário adiar algumas operações de inicialização de objetos de alta sobrecarga e só é inicializado ao usar esses objetos. Isso é chamado de inicialização tardia ou carregamento preguiçoso
Veja uma inicialização de atraso inseguro:
Após o thread A executa 1, ele descobre que a instância do objeto é nula e está pronta para a nova, enquanto o Thread B é o novo primeiro, o que causa um erro.
Podemos usar bloqueios de sincronização para garantir a correção:
Mas sincronizar todo o método é muito caro, e as pessoas criaram bloqueio de verificação dupla:
O bloqueio de sincronização usado no intervalo mínimo parece alcançar o objetivo usando a verificação dupla, mas isso tem um problema: quando um Thread 4, o Thread B de Thread B ainda não foi executado e Thread A Determine Instância! = NULL. O Thread B 7 ainda não foi executado, então por que isso acontece?
Dê uma olhada na principal implementação subjacente de New Instância ():
De fato, é primeiro executar 1 alocar memória, inicializar o objeto e definir a instância. Depois, há uma reordenação aqui, e a ordem de 2 e 3 pode ser substituída:
Portanto, quando B ainda executa 7, A determina em 4 que o objeto de instância foi inicializado. Se a instância for chamada antes do ctorInstance (memória) causará um erro.
Existem duas soluções:
1. Declare o objeto de instância como volátil, ele proibirá a reordenação de 2 e 3
2. Usando uma solução baseada na inicialização da classe: a JVM executará a inicialização da classe no estágio de inicialização da classe (ou seja, após a classe é carregada e antes de ser usada pelo encadeamento). existe
Durante a inicialização da classe de execução, a JVM adquirirá um bloqueio. Este bloqueio pode sincronizar a inicialização da mesma classe por vários threads
Descobriremos que o código de implementação do esquema com base na inicialização da classe é mais simples. Mas o esquema de bloqueio de verificação duplo com base no volátil tem uma vantagem adicional: além da inicialização do atraso dos campos estáticos, também pode atrasar a inicialização dos campos de instância. A inicialização do atraso de campo reduz a sobrecarga da inicialização de classes ou da criação de instâncias, mas aumenta a sobrecarga dos campos de acesso que são atrasados. Na maioria das vezes, a inicialização normal é melhor do que a inicialização atrasada. Se você realmente precisar usar a inicialização tardia segura por threads, por exemplo, campos, use o esquema de inicialização de atraso baseado em voláteis descrito acima; Se você realmente precisar usar a inicialização tardia segura por threads para campos estáticos, use o esquema de inicialização baseado em classe descrito acima.
Resumir
O exposto acima é o código de implementação do bloqueio de verificação dupla Java introduzido pelo editor. Espero que seja útil para todos. Se você tiver alguma dúvida, deixe -me uma mensagem e o editor responderá a todos a tempo. Muito obrigado pelo seu apoio ao site wulin.com!