bloqueo de java y verificación doble

Bloqueo de control doble / bloqueo de control doble El juicio antiaéreo de doble capa ha sido problemático durante mucho tiempo. Ejemplo

public class Singleton {
    private volatile static Singleton singleton;

  //私有构造函数避免调用
    private Singleton (){}
    public static Singleton getSingleton() {

    // 先判断对象是否创建过
        if (singleton == null) {

        //类对象加锁
            synchronized (Singleton.class) {
                if (singleton == null) {
                    singleton = new Singleton();
                    //字节码层
                    //JIT CPU 可能对如下指令进行重排序
                    // 1.分配空间
                    // 2.初始化
                    // 3.引用赋值
                    如果指令重排后指令如下:
                    //1.分配空间
                    //3.引用赋值 如果在当前指令执行完后,有其他线程获取到实例,将拿到未初始化的实例;
                    //2. 初始化
                }
            }
        }
        return singleton;
    }
}


Explicación: Cuando A y B llaman a getSingleton al mismo tiempo, se juzga que el primero si está vacío. En este momento, A obtiene el bloqueo y realiza el segundo nivel si se juzga. La condición se establece y un objeto es nuevo;

B espera en la capa exterior, se crea A, se libera el candado, B obtiene el candado y el segundo nivel si se realiza el juicio, no se establece la condición y se libera el candado. Cuando C llama a getSingleton, no se establece el primer nivel de juicio y el objeto singleton se devuelve directamente para evitar ingresar al bloqueo y reducir la sobrecarga de rendimiento.

Comprensión adicional: dos de ellos están vacíos, el primero vacío es para reducir el número de veces para ingresar al bloque de código de sincronización en el caso de subprocesos múltiples, y el segundo vacío es para evitar el subproceso múltiple (A, B en el caso de dos subprocesos) , B llama al método getSingleton al mismo tiempo, y al mismo tiempo, ingresa a la primera capa si (singleton == null) {}. En condiciones de carrera, si A obtiene el bloqueo de objeto, ingresa al bloque de código síncrono y B bloques esperando, esperando Después de que se crea el objeto de instancia y se libera el bloqueo, B ingresa al bloque de código de sincronización, pero en este momento el segundo nivel if (singleton == null) {} juzga que singleton no está vacío y devuelve singleton directamente );

Resumen: Hay dos declaraciones para determinar si está vacío. La primera vez es para mejorar la eficiencia y evitar ejecutar bloques de código sincronizados cada vez. La segunda vez es para evitar la inseguridad causada por el multihilo. Cuando dos hilos juzgan que el primero es vacíos al mismo tiempo, todos entrarán en el bloque de código de sincronización uno tras otro En este momento, si no hay una segunda condición de vacío, se crearán múltiples instancias.

palabras clave de volite:

Es necesario utilizar la modificación de palabras clave volátiles.

En realidad, este código se divide en tres pasos:

singleton = nuevo Singleton ();

  1. Asignar espacio de memoria para singleton
  2. Inicializar singleton 
  3. Apunte el singleton a la dirección de memoria asignada.
    Sin embargo, jvm tiene las características de reordenamiento de instrucciones, y el orden de ejecución puede cambiar, no en el orden de 123, pero puede ser 132, lo que hará que un hilo obtenga una instancia no inicializada
    como : t1 se ejecuta 13. En este momento, después de que t2 llama a getInstance (), se encuentra que el singleton ya no está vacío, por lo que se devuelve singleton, pero en este momento, el singleton no se ha inicializado como
    volátil y la instrucción jvm se reordena se puede prohibir para garantizar que pueda ser normal en un entorno multiproceso ejecutado

Quiere saber más: Recomendar

Comprensión profunda del principio de implementación sincronizada de la concurrencia de Java

https://blog.csdn.net/javazejian/article/details/72828483

 

referencia:

https://blog.csdn.net/jlnu0812407/article/details/102836187

https://blog.csdn.net/faye_1008/article/details/90296173

Supongo que te gusta

Origin blog.csdn.net/JHON07/article/details/103048352
Recomendado
Clasificación