La palabra clave volátil se utiliza para modificar el valor de una variable mediante diferentes subprocesos. También se utiliza para hacer que las clases sean seguras para subprocesos. Significa que varios subprocesos pueden utilizar un método y una instancia de las clases al mismo tiempo sin ningún problema. La palabra clave volátil se puede utilizar con tipos primitivos u objetos.
La palabra clave volátil no almacena en caché el valor de la variable y siempre lee la variable desde la memoria principal. La palabra clave volátil no se puede utilizar con clases o métodos. Sin embargo, se utiliza con variables. También garantiza visibilidad y orden. Evita que el compilador reordene el código.
cpld y fpga
El contenido del 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.
Ejemplo
class Test { static int var=5; }
En el ejemplo anterior, supongamos que dos subprocesos están trabajando en la misma clase. Ambos subprocesos se ejecutan en procesadores diferentes donde cada subproceso tiene su copia local de var. Si algún hilo modifica su valor, el cambio no se reflejará en el original en la memoria principal. Conduce a una inconsistencia en los datos porque el otro hilo no conoce el valor modificado.
class Test { static volatile int var =5; }
En el ejemplo anterior, las variables estáticas son miembros de clase que se comparten entre todos los objetos. Sólo existe una copia en la memoria principal. El valor de una variable volátil nunca se almacenará en la memoria caché. Toda la lectura y escritura se realizará desde y hacia la memoria principal.
¿Cuándo usarlo?
- Puede utilizar una variable volátil si desea leer y escribir variables largas y dobles automáticamente.
- Puede utilizarse como una forma alternativa de lograr la sincronización en Java.
- Todos los hilos del lector verán el valor actualizado de la variable volátil después de completar la operación de escritura. Si no está utilizando la palabra clave volátil, diferentes hilos de lectores pueden ver valores diferentes.
- Se utiliza para informar al compilador que varios subprocesos accederán a una declaración en particular. Impide que el compilador realice cualquier reordenamiento u optimización.
- Si no utiliza el compilador de variables volátiles, puede reordenar el código y escribir en el caché el valor de la variable volátil en lugar de leerlo desde la memoria principal.
Puntos importantes
- Puede utilizar la palabra clave volátil con variables. Usar palabras clave volátiles con clases y métodos es ilegal.
- Garantiza que el valor de la variable volátil siempre se leerá desde la memoria principal, no desde la caché de subprocesos local.
- Si declaró la variable como volátil, las lecturas y escrituras son atómicas
- Reduce el riesgo de error de coherencia de la memoria.
- Cualquier escritura en una variable volátil en Java establece un suceso antes de la relación con lecturas sucesivas de esa misma variable.
- Las variables volátiles siempre son visibles para otros hilos.
- La variable volátil que es una referencia de objeto puede ser nula.
- Cuando una variable no se comparte entre varios subprocesos, no es necesario utilizar la palabra clave volátil con esa variable.
Diferencia entre sincronización y palabra clave volátil
La palabra clave volátil no sustituye a la palabra clave sincronizada, pero puede utilizarse como alternativa en determinados casos. Existen las siguientes diferencias:
Palabra clave volátil | Palabra clave de sincronización |
---|---|
La palabra clave volátil es un modificador de campo. | La palabra clave sincronizada modifica bloques de código y métodos. |
El hilo no se puede bloquear por espera en caso de volátil. | Los subprocesos se pueden bloquear para esperar en caso de sincronización. |
Mejora el rendimiento del hilo. | Los métodos sincronizados degradan el rendimiento del hilo. |
Sincroniza el valor de una variable a la vez entre la memoria del subproceso y la memoria principal. | Sincroniza el valor de todas las variables entre la memoria del subproceso y la memoria principal. |
Los campos volátiles no están sujetos a la optimización del compilador. | Sincronizar está sujeto a la optimización del compilador. |
Ejemplo de palabra clave volátil
En el siguiente ejemplo, hemos definido una clase que aumenta el valor del contador. El método run () en VolatileThread.java obtiene el valor actualizado y el valor anterior cuando el hilo comienza a ejecutarse. En la clase principal, definimos la matriz de subprocesos.
VolatileData.java
public class VolatileData { private volatile int counter = 0; public int getCounter() { return counter; } public void increaseCounter() { ++counter; //increases the value of counter by 1 } }
VolatileThread.java
VolatileThread.java public class VolatileThread extends Thread { private final VolatileData data; public VolatileThread(VolatileData data) { this.data = data; } @Override public void run() { int oldValue = data.getCounter(); System.out.println('[Thread ' + Thread.currentThread().getId() + ']: Old value = ' + oldValue); data.increaseCounter(); int newValue = data.getCounter(); System.out.println('[Thread ' + Thread.currentThread().getId() + ']: New value = ' + newValue); } }
VolatileMain.java
milivericket
public class VolatileMain { private final static int noOfThreads = 2; public static void main(String[] args) throws InterruptedException { VolatileData volatileData = new VolatileData(); //object of VolatileData class Thread[] threads = new Thread[noOfThreads]; //creating Thread array for(int i = 0; i <noofthreads; ++i) threads[i]="new" volatilethread(volatiledata); for(int i="0;" < noofthreads; threads[i].start(); starts all reader threads threads[i].join(); wait for } pre> <p> <strong>Output:</strong> </p> <pre> [Thread 9]: Old value = 0 [Thread 9]: New value = 1 [Thread 10]: Old value = 1 [Thread 10]: New value = 2 </pre> <hr></noofthreads;>