Java doble detección de singleton

Ejemplo 1. El modo único en general como sigue:

clase Singleton {
    private static Singleton;   
    Singleton privada () {}
       
    public static Singleton getInstance () {
        si (Singleton == null) {
            Singleton Singleton = new (); //创建实例
    }
    retorno Singleton;
    }

Pregunta: constructor tan privado que el mundo exterior no se pueden crear instancias de constructor de la clase Singleton, para obtener ejemplos sólo a través de () método getInstance. Esta es una versión de carga diferida, que se crea una instancia objeto sólo funcionan cuando es necesario. Este método funciona correctamente en un solo hilo, pero la situación porque no hay sincronización medidas conducen a una mayor objeto singleton aparecerá en un entorno multiproceso.

Así que, si bien puede haber dos hilos A y B se realizan simultáneamente si la declaración condicional, se determina Singleton A es vacío listo para ejecutar (// crear una instancia) de un intervalo de tiempo de CPU, también se determinó Singleton B está vacía, a continuación, ejecutar: Razón un caso se lleva a cabo a continuación, después de la obtención de la porción de tiempo de CPU (// crear ejemplo), sino también crear una instancia de un objeto, lo que conduce a una pluralidad de objeto singleton; (// Crear ejemplo), a continuación, crear una instancia del objeto

2. Con el fin de resolver el problema es que se produzca en 1 para usar la palabra clave sincronizada, como sigue:

clase Singleton {
    private static Singleton;   
    Singleton privada () {}
       
    public static Singleton getInstance sincronizado () {
        si (Singleton == null) {
            Singleton Singleton = new (); //创建实例
        }
        retorno Singleton;
    }
}

Esto resuelve el problema de la eficiencia simultánea multi-hilo, pero ha traído: Nuestro objetivo es crear una sola instancia, a saber, (// crear una instancia) en el código de una sola vez, sino que también es el único lugar para estar sincronizados, detrás después se crea la instancia, devolverá directamente Singleton no nulo referencia de objeto, pero no cada bloque de verificación de código de sincronización no vacío.

3. Con el fin de resolver los problemas que ocurren en sólo 2 (// crear una instancia) en sincronizada:

clase Singleton {
    private static Singleton;   
    Singleton privada () {}
   
    public static Singleton getInstance () {
        si (Singleton == null) {
            sincronizada (Singleton.class) {               
                Singleton Singleton = new (); //创建实例
            }
        }
        retorno Singleton;
    }
}

Esto hará que el mismo problema con la primera: es decir, varios subprocesos para ejecutar simultáneamente sentencia condicional, crea varias instancias.

La razón: el problema es que cuando se crea una instancia de un hilo, Singleton ya no está vacía, pero el hilo de seguimiento no hacer una segunda comprobación no está vacía

4. Con el fin de resolver los problemas que ocurren es 3 en la segunda rosca posterior no código de comprobación de vacío es como sigue:

clase Singleton {
    private static Singleton;   
    Singleton privada () {}
   
    public static Singleton getInstance () {
        si (Singleton == null) {
            sincronizada (Singleton.class) {
                si (Singleton == null)
                    Singleton Singleton = new (); //创建实例
            }
        }
        retorno Singleton;
    }
}

Aquí era perfecto, parece que no hay problema. ¡No! ! ! Debido a este mecanismo de detección dual antes de JDK1.5 es un problema, el problema aún se encuentra en el (// crear una instancia), escrito por el trastorno llamado causado.

En general, cuando un objeto se inicializa cuando la experiencia

  a. de asignación de memoria

  b. inicialización

  c. devolver una referencia de objeto

  a. la asignación de memoria,

  b. devolver una referencia de objeto

  c. secuencia de inicialización,

En este caso corresponde a (// crear una instancia) es el singleton no es nulo, pero los puntos a un objeto en el montón, pero el objeto todavía no se ha completado la acción de inicialización. Cuando un posterior hilo singleton encontró nula y no se utiliza directamente cuando se producen problemas inesperados.

Solución: Después de JDK1.5, puede utilizar la palabra clave volátil variables modificadas para resolver los problemas que surjan de orden escrita, porque un papel significativo en la palabra clave volátil está prohibido reordenamiento de instrucciones, es decir, garantizar que la asignación de memoria no aparece para devolver una referencia de objeto , una secuencia de este tipo de inicialización, de manera que el verdadero papel de detección dual

unidad de detección 5. Modo Finalmente dual Ejemplo:

public class Singleton {

    ejemplo Singleton estática volátil privado = null;
    Singleton privada () {}

    public static Singleton getInstance () {
            si (ejemplo == null) {
                sincronizada (Singleton.class) {
                    si (ejemplo == null) {
                        instancia = new Singleton ();
                    }
                }
            }
            Regresar ejemplo;
    }
}

Supongo que te gusta

Origin www.linuxidc.com/Linux/2020-03/162647.htm
Recomendado
Clasificación