Palabra clave volátil en Java

El uso de volatile es otra forma (como el envoltorio atómico sincronizado) de hacer que la clase sea segura para subprocesos. Seguro para subprocesos significa que un método o instancia de clase puede ser utilizado por múltiples subprocesos al mismo tiempo sin ningún problema. Considere el siguiente ejemplo. 

class SharedObj
{
   // Changes made to sharedVar in one thread
   // may not immediately reflect in other thread
   static int sharedVar = 6;
}

Supongamos que dos subprocesos están trabajando en SharedObj . Si dos subprocesos se ejecutan en diferentes procesadores, cada subproceso puede tener su propia copia local de sharedVariable . Si un subproceso modifica su valor, es posible que el cambio no se refleje en el original en la memoria principal al instante. Esto depende de la política de escritura de la memoria caché. Ahora, el otro subproceso no es consciente del valor modificado, lo que conduce a la inconsistencia de los datos. 

El siguiente diagrama muestra que si dos subprocesos se ejecutan en diferentes procesadores, entonces el valor de sharedVariable puede ser diferente en diferentes subprocesos. 

volatileJava

Tenga en cuenta que la escritura de variables normales sin ninguna acción de sincronización puede no ser visible para ningún subproceso de lectura (este comportamiento se denomina consistencia secuencial ). Aunque la mayoría del hardware moderno proporciona una buena coherencia de caché, lo más probable es que los cambios en un caché se reflejen en otro, pero no es una buena práctica confiar en el hardware para «arreglar» una aplicación defectuosa. 

class SharedObj
{
   // volatile keyword here makes sure that
   // the changes made in one thread are 
   // immediately reflect in other thread
   static volatile int sharedVar = 6;
}

Tenga en cuenta que volátil no debe confundirse con el modificador estático. Las variables estáticas son miembros de clase que se comparten entre todos los objetos. Solo hay una copia de ellos en la memoria principal. 

volátil vs sincronizado: antes de continuar, echemos un vistazo a dos características importantes de los bloqueos y la sincronización. 

  1. Exclusión Mutua: Significa que solo un hilo o proceso puede ejecutar un bloque de código (sección crítica) a la vez.
  2. Visibilidad : significa que los cambios realizados por un subproceso en los datos compartidos son visibles para otros subprocesos.

La palabra clave sincronizada de Java garantiza tanto la exclusión mutua como la visibilidad. Si sincronizamos los bloques de hilos que modifican el valor de la variable compartida, solo un hilo puede entrar en el bloque y los cambios realizados por él se reflejarán en la memoria principal. Todos los demás subprocesos que intenten ingresar al bloque al mismo tiempo se bloquearán y se suspenderán. 

En algunos casos, es posible que solo deseemos visibilidad y no atomicidad. El uso de sincronizado en tal situación es excesivo y puede causar problemas de escalabilidad. Aquí volátil viene al rescate. Las variables volátiles tienen las características de visibilidad de las sincronizadas pero no las características de atomicidad. Los valores de la variable volátil nunca se almacenarán en caché y todas las escrituras y lecturas se realizarán desde y hacia la memoria principal. Sin embargo, el uso de volátiles se limita a un conjunto muy restringido de casos, ya que la mayoría de las veces se desea atomicidad. Por ejemplo, una declaración de incremento simple como x = x + 1; o x ++ parece ser una sola operación, pero en realidad es una secuencia compuesta de operaciones de lectura, modificación y escritura que debe ejecutarse atómicamente. 

Java

// Java Program to demonstrate the
// use of Volatile Keyword in Java
 
public class VolatileTest {
    private static final Logger LOGGER
        = MyLoggerFactory.getSimplestLogger();
    private static volatile int MY_INT = 0;
   
    public static void main(String[] args)
    {
        new ChangeListener().start();
        new ChangeMaker().start();
    }
   
    static class ChangeListener extends Thread {
        @Override public void run()
        {
            int local_value = MY_INT;
            while (local_value < 5) {
                if (local_value != MY_INT) {
                    LOGGER.log(
                        Level.INFO,
                        "Got Change for MY_INT : {0}",
                        MY_INT);
                    local_value = MY_INT;
                }
            }
        }
    }
   
    static class ChangeMaker extends Thread {
        @Override public void run()
        {
            int local_value = MY_INT;
            while (MY_INT < 5) {
                LOGGER.log(Level.INFO,
                           "Incrementing MY_INT to {0}",
                           local_value + 1);
                MY_INT = ++local_value;
                try {
                    Thread.sleep(500);
                }
                catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

Salida (con la palabra clave volátil):

Incrementing MY_INT to 1
Got Change for MY_INT : 1
Incrementing MY_INT to 2
Got Change for MY_INT : 2
Incrementing MY_INT to 3
Got Change for MY_INT : 3
Incrementing MY_INT to 4
Got Change for MY_INT : 4
Incrementing MY_INT to 5
Got Change for MY_INT : 5

Salida (sin la palabra clave volátil)

Incrementing MY_INT to 1
Incrementing MY_INT to 2
Incrementing MY_INT to 3
Incrementing MY_INT to 4
Incrementing MY_INT to 5

volátil en Java vs C/C++: 

Volátil en Java es diferente del calificador «volátil» en C/C++ . Para Java, «volátil» le dice al compilador que el valor de una variable nunca debe almacenarse en caché, ya que su valor puede cambiar fuera del alcance del programa en sí. En C/C++, se necesita «volátil» cuando se desarrollan sistemas integrados o controladores de dispositivos, donde se necesita leer o escribir un dispositivo de hardware asignado a la memoria. El contenido de un registro de dispositivo en particular podría cambiar en cualquier momento, por lo que necesita la palabra clave «volátil» para asegurarse de que el compilador no optimice dichos accesos. 

Este artículo es una contribución de Sulabh Kumar . Escriba comentarios si encuentra algo incorrecto o si desea compartir más información sobre el tema tratado anteriormente. 

Publicación traducida automáticamente

Artículo escrito por GeeksforGeeks-1 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *