palabra clave volátil (variable modificada)

1. Significado

Es un mecanismo de sincronización más ligero que la palabra clave sincronizada, al acceder a variables volátiles no se realizan operaciones de bloqueo.

2. Función

Volátil es un especificador de tipo. La función de volatile se utilizará como palabra clave de instrucción para garantizar que esta instrucción no se omita debido a la optimización del compilador y que requiera lectura directa en todo momento.

  1. Asegurar la visibilidad
  2. Deshabilitar la optimización de reordenamiento de instrucciones

Optimización del reordenamiento de instrucciones: las variables ordinarias solo garantizan que se puedan obtener los resultados correctos en todos los lugares que dependen de los resultados de la asignación durante la ejecución del método, pero no pueden garantizar que el orden de las operaciones de asignación de variables sea coherente con el orden de ejecución en el código del programa

3. Cómo garantizar la visibilidad

El nuevo valor puede sincronizarse inmediatamente con la memoria principal y actualizarse desde la memoria principal inmediatamente antes de cada uso.

  • La variable modificada por volátil es el valor de la memoria principal que se toma directamente, es decir, el valor es siempre el último y es visible para otros hilos.

  • Al acceder a una variable no volátil, cada hilo copia la variable de la memoria del sistema (memoria principal) a la memoria de trabajo, y luego modifica el valor de la variable en la memoria de trabajo. La variable manipulada puede ser diferente.

4. Cómo deshabilitar la optimización de reordenamiento de instrucciones

volatile prohíbe el reordenamiento de la optimización estableciendo una barrera de memoria Java.
Barrera de memoria de Java La barrera de
memoria, también conocida como barrera de memoria o instrucción de barrera, es una instrucción de barrera que permite a la CPU o al compilador realizar una restricción de clasificación en las operaciones de memoria emitidas antes y después de la instrucción de barrera. Esto generalmente significa que se garantiza que las operaciones emitidas antes de la barrera se ejecutarán antes que las operaciones emitidas después de la barrera.
Las cuatro llamadas barreras de memoria de Java, a saber, LoadLoad, StoreStore, LoadStore, StoreLoad, son en realidad una combinación de las dos anteriores, completando una serie de barreras y funciones de sincronización de datos.
(Cargar comando (es decir, leer de la memoria), Guardar comando (es decir, escribir en la memoria).)

  • Barrera LoadLoad: Para tales declaraciones Load1; LoadLoad; Load2, antes de que se acceda a
    los datos a leer por Load2 y las operaciones de lectura posteriores, se garantiza que los datos a leer por Load1 han sido leídos.

  • Barrera StoreStore: Para tales declaraciones Store1; StoreStore; Store2, antes de que se ejecuten Store2
    y las operaciones de escritura posteriores, se garantiza que las operaciones de escritura de Store1 sean visibles para otros procesadores.

  • Barrera LoadStore: Para tales declaraciones Load1; LoadStore; Store2, antes de que Store2
    y las operaciones de escritura subsiguientes se eliminen , asegúrese de que los datos que debe leer Load1 se hayan leído.

  • Barrera StoreLoad: Para tales declaraciones Store1; StoreLoad; Load2, antes de que se ejecuten Load2
    y todas las operaciones de lectura posteriores, se garantiza que las escrituras Store1 sean visibles para todos los procesadores. Su techo es la mayor de las cuatro barreras. En la mayoría de las implementaciones de procesadores, esta barrera es una barrera universal, que tiene las funciones de las otras tres barreras de memoria.

¿Qué hace volátil?
Después de que una variable es modificada por volátil, la JVM hará dos cosas por nosotros:

  • Inserte la barrera StoreStore antes de cada operación de escritura volátil y la barrera StoreLoad después de la operación de escritura. (StoreStore-Write-StoreLoad)

  • Inserte una barrera LoadLoad antes de cada operación de lectura volátil e inserte una barrera LoadStore después de la operación de lectura. (LoadLoad-Read-LoadStore)

5. Lo volátil no es seguro

Aunque la visibilidad volátil asegura que todas las operaciones de escritura en variables volátiles se puedan reflejar inmediatamente en otros subprocesos (es decir, las variables volátiles son consistentes en cada subproceso), las operaciones en Java no son operaciones atómicas. Solo las variables volátiles que son operaciones atómicas son seguras para subprocesos, como nuestra operación de autoincremento variable ++ muy común. En este proceso, el autoincremento incluye las operaciones de obtener, agregar uno y guardar los tres procesos, por lo que el autoincremento se combina No es una operación atómica y aún no es seguro usar la operación de incremento variable modificada volátil.

por ejemplo:

public class MyVolitile {
    
    

    private static volatile int count = 0;

    public static void main(String[] args) {
    
    
        for (int i = 0; i < 2; i++) {
    
    
            new Thread(new Runnable() {
    
    
                @Override
                public void run() {
    
    
                    for (int i = 0; i < 100; i++) {
    
    
                        count++;
                    }
                }
            }).start();
        }
        try {
    
    
            Thread.sleep(300);
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }

        System.out.println(count);
    }
    
}

El resultado es diferente cada vez, no necesariamente igual a 200.

6. Escenarios inadecuados para volátiles

Dado que las variables volátiles solo pueden garantizar la visibilidad, en escenarios informáticos que no cumplen con las siguientes dos reglas, todavía tenemos que bloquear (usando clases sincronizadas o atómicas en java.util.concurrent) para garantizar la atomicidad.

  1. El resultado de la operación no depende del valor actual de la variable, o puede garantizar que solo un hilo modifique el valor de la variable
  2. Las variables no necesitan participar en restricciones invariantes con otras variables de estado

Supongo que te gusta

Origin blog.csdn.net/weixin_44395707/article/details/106688830
Recomendado
Clasificación