Problema volátil distribuido y de alta visibilidad de concurrencia (1)

1. Casos en los que se producirán problemas de visibilidad

1.1, conduce a problemas de visibilidad

public class VolatileDemo {
    
    
    public static boolean stop=true;

    public static void main(String[] args) throws InterruptedException {
    
    
        new Thread(()->{
    
    
            int i=0;
            while (stop){
    
    
                i++;
            }
            System.out.println("循环结束:"+i);
        }).start();
        Thread.sleep(1000);
        stop=false;
    }
}

1.2, resultados de ejecución

Inserte la descripción de la imagen aquí

1.3 Análisis de resultados de ejecución

Se puede ver que el bucle no ha terminado y no hay salida: System.out.println ("Fin del bucle:" + i); entonces stop = false en el hilo principal, invisible para el hilo secundario while (stop) , este es un problema de visibilidad

2. Utilice imprimir para sincronizar la memoria principal

2.1 Implementación del código

public class VolatileDemo {
    
    
    public static boolean stop=true;

    public static void main(String[] args) throws InterruptedException {
    
    
        new Thread(()->{
    
    
            int i=1;
            while (stop){
    
    
                i++;
                System.out.println("最新数据:"+i);
            }
        }).start();
        Thread.sleep(100);
        stop=false;
    }
}

2.2, resultados de ejecución

Inserte la descripción de la imagen aquí

2.3 Análisis de resultados

El hilo termina normalmente, entonces, ¿cómo contribuye la impresión a la resolución del problema de visibilidad?

El método de impresión se divide principalmente en dos pasos

  1. Operación de IO: el bloqueo de IO también tendrá un impacto, el soporte de código (nuevo Archivo ()), también hará que el código finalice normalmente
public class VolatileDemo {
    
    
    //添加volatile关键字
    public static boolean stop=true;

    public static void main(String[] args) throws InterruptedException {
    
    
        new Thread(()->{
    
    
            int i=1;
            while (stop){
    
    
                i++;
                new File("text.txt");
            }
        }).start();
        Thread.sleep(100);
        stop=false;
    }
}

  1. sincronizado: La liberación del bloqueo obligará a que la operación escrita en la memoria de trabajo se sincronice con la memoria principal, lo que significa stop = falso, y el valor de stop se sincronizará con la memoria principal. El siguiente ciclo de while se leerá stop = false; para esto Conclusión Para probarlo, el resultado de la ejecución del siguiente código también terminará normalmente, por lo que la conclusión es que el bloqueo sincronizado y la liberación de bloqueos sincronizarán la memoria principal
public class VolatileDemo {
    
    
    public static boolean stop=true;

    public static void main(String[] args) throws InterruptedException {
    
    
        new Thread(()->{
    
    
            int i=1;
            while (stop){
    
    
                i++;
                synchronized (VolatileDemo.class){
    
    
                    
                }
            }
        }).start();
        Thread.sleep(100);
        stop=false;
    }
}

En resumen, la impresión realiza operaciones de sincronización e io, por lo que se resuelve el problema de visibilidad

3. Thread.sleep resuelve el problema de visibilidad

sleep: no hay una operación de sincronización, lo que provocará el cambio de hilo, la re-competencia del hilo, la reasignación de recursos del sistema, lo que provocará que falle la memoria caché original del hilo y la recarga del nuevo valor en la memoria principal

public class VolatileDemo {
    
    
    public static boolean stop=true;

    public static void main(String[] args) throws InterruptedException {
    
    
        new Thread(()->{
    
    
            int i=1;
            while (stop){
    
    
                i++;
                try {
    
    
                    Thread.sleep(0);
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                }
            }
        }).start();
        Thread.sleep(100);
        stop=false;
    }
}

4. Agregue la palabra clave volátil

4.1, implementación de código

public class VolatileDemo {
    
    
    //添加volatile关键字
    public volatile static boolean stop=true;

    public static void main(String[] args) throws InterruptedException {
    
    
        new Thread(()->{
    
    
            int i=1;
            while (stop){
    
    
                i++;
            }
            System.out.println("循环结束:"+i);
        }).start();
        Thread.sleep(100);
        stop=false;
    }
}

4.2, resultados de ejecución

Inserte la descripción de la imagen aquí

4.3 Análisis de resultados

El programa finaliza normalmente y se emite un mensaje que indica que se captura stop = false en el subbucle

5. Resumen

En resumen, podemos ver que podemos usar la palabra clave volatile para resolver el problema de visibilidad, por lo que no es necesario preocuparse por si hay operaciones de código como imprimir o dormir en el hilo.

Supongo que te gusta

Origin blog.csdn.net/qq_28500837/article/details/110111257
Recomendado
Clasificación