El patrón perezoso singleton de superficial a profundo

1. La versión más básica, no tiene en cuenta los problemas de seguridad de los subprocesos.

package JavaBasis.chapter8;

public class Singleton {
    
    
    private static Singleton instance=null;
    private Singleton(){
    
    }//私有化构造函数,外部不可见
    private static Singleton getInstance()
    {
    
    
           if(instance==null)//实例未被创建
           instance=new Singleton();

           return instance;//返回创建的实例
    }
}

2. La introducción de problemas de subprocesos múltiples

El código anterior tiene problemas de inseguridad de subprocesos en un entorno multiproceso. Por ejemplo, el subproceso 1 se ejecuta primero en la sentencia if y descubre que la instancia no se ha creado, por lo que comienza a crear la instancia; en este momento, el subproceso 2 viene de nuevo, pero la instancia del hilo 1 aún no lo ha hecho Después de la creación, el juicio if aún se cumple, y luego el hilo 2 ingresa a la declaración de creación, lo que da como resultado dos objetos instace al final

  • Solución 1 Agregue un candado a todo el método
package JavaBasis.chapter8;

public class Singleton {
    
    
    private static Singleton instance=null;
    private Singleton(){
    
    }//私有化构造函数,外部不可见
    private static synchronized Singleton getInstance()
    {
    
    
           if(instance==null)//实例未被创建
           instance=new Singleton();

           return instance;//返回创建的实例
    }
}

Esta solución puede resolver el problema de seguridad de subprocesos, pero hay otro problema. Debido a que todo el método está bloqueado, supongamos que ahora tengo un subproceso 1 que obtiene el bloqueo e ingresa el método para crear el objeto. El subproceso 1 termina y luego el subproceso 2 viene y el método encuentra que el objeto ha sido creado y regresa directamente, pero si el hilo 3 también llega en este momento, porque todo el método está bloqueado, el hilo 3 no puede entrar. Debe esperar a que el hilo 2 termine antes de que pueda entrar, pero solo quiere devolver un objeto que ha sido creado, perdiendo tiempo e incurriendo en gastos generales de rendimiento, y luego puede llegar a la siguiente solución

  • Solución 2 Agregar sincronizado al proceso de creación
package JavaBasis.chapter8;

public class Singleton {
    
    
    private static Singleton instance=null;
    private Singleton(){
    
    }//私有化构造函数,外部不可见
    private  static  Singleton getInstance()
    {
    
           if(instance==null)//实例未被创建
           {
    
    
           synchronized(Singleton.class)
           {
    
     instance=new Singleton();
           }
           }

           return instance;//返回创建的实例
    }
}

El código anterior también tiene problemas de seguridad de subprocesos. Ahora el subproceso 1 ingresa primero al método y obtiene el bloqueo para comenzar a crear el objeto. Antes de que se cree el objeto del subproceso 1, el subproceso 2 también entra. El subproceso 2 juzga si encuentra que el objeto tiene no se ha creado, así que Enter, pero no puede obtener el bloqueo, por lo que comienza a esperar. Después de que el hilo 1 crea el objeto y libera el bloqueo, el hilo 2 crea el objeto nuevamente, porque ya ha realizado un juicio if antes

  • Solución 3 Cerradura de doble inspección
package JavaBasis.chapter8;

public class Singleton {
    
    
    private static Singleton instance=null;
    private Singleton(){
    
    }//私有化构造函数,外部不可见
    private  static  Singleton getInstance()
    {
    
           if(instance==null)//实例未被创建
           {
    
    
           synchronized(Singleton.class)
           {
    
     
           if(instance==null)
           instance=new Singleton();
           }
           }

           return instance;//返回创建的实例
    }
}

El problema anterior se puede resolver agregando un juicio al problema del esquema 2, como el hilo 2 mencionado en el esquema 2, aunque ha pasado el primer juicio if, cuando obtenga el bloqueo, realizará el juicio if. se encuentra que el objeto ha sido creado por el hilo 1, por lo que se devuelve directamente al objeto, hasta ahora, ¿cree que ha terminado, pero incluso si es un bloqueo de doble verificación, hay ciertos problemas

      if(instance==null)//实例未被创建
           {
    
    
           synchronized(Singleton.class)
           {
    
     
           if(instance==null)
           instance=new Singleton();//1
           }
           }

Al observar este código, el proceso de creación de un objeto se divide en los siguientes tres pasos:
1. Asignar el espacio de memoria del
objeto 2. Inicializar el objeto
3. Dejar que la referencia de la instancia apunte a la dirección del objeto inicializado,
pero la instrucción el reordenamiento ocurre en Java Específicamente, se cambiará el orden de 2 y 3. Puede ejecutar 3 y luego ejecutar 2. ¿Qué problemas causará esto?
Por ejemplo: el hilo 1 ingresa al bloque de código sincronizado y comienza a crear objetos, ejecuta 1, y luego ejecuta 3. Después de que la ejecución de 3instance no es nula, la instancia apunta a una dirección clara, pero el objeto en esta dirección no se inicializa. Cuando el subproceso 1 no ha tenido tiempo de realizar la operación 2, el subproceso 2 entra y encuentra la primera instrucción if (o tal vez es la segunda instrucción if) La instancia dentro no es nula, por lo que la instancia se
devuelve directamente, pero la instancia es un objeto no inicializado. Solución: agregue la palabra clave volitile delante de la instancia y la se cerrará el reordenamiento de instrucciones.

Supongo que te gusta

Origin blog.csdn.net/qq_43478694/article/details/114966158
Recomendado
Clasificación