¿Para qué sirve la palabra clave volátil?
Hoy en el trabajo, encontré la volatile
palabra clave en Java. Al no estar muy familiarizado con ello, encontré esta explicación .
Dado el detalle en el que ese artículo explica la palabra clave en cuestión, ¿la usa alguna vez o podría ver algún caso en el que pueda usar esta palabra clave de la manera correcta?
volatile
tiene semántica para la visibilidad de la memoria. Básicamente, el valor de un volatile
campo se vuelve visible para todos los lectores (otros hilos en particular) después de que se completa una operación de escritura en él. Sin volatile
, los lectores podrían ver algún valor no actualizado.
Para responder a su pregunta: Sí, uso una volatile
variable para controlar si algún código continúa un bucle. El bucle prueba el volatile
valor y continúa si es true
. La condición se puede establecer false
llamando a un método de "detención". El bucle detecta false
y finaliza cuando prueba el valor después de que el método de detención completa la ejecución.
El libro " Java Concurrency in Practice ", que recomiendo encarecidamente, ofrece una buena explicación volatile
. Este libro está escrito por la misma persona que escribió el artículo de IBM al que se hace referencia en la pregunta (de hecho, cita su libro al final de ese artículo). Mi uso volatile
es lo que su artículo llama "indicador de estado del patrón 1".
Si desea obtener más información sobre cómo volatile
funciona internamente, lea sobre el modelo de memoria Java . Si desea ir más allá de ese nivel, consulte un buen libro sobre arquitectura informática como Hennessy & Patterson y lea sobre coherencia de caché y consistencia de caché.
"... el modificador volátil garantiza que cualquier hilo que lea un campo verá el valor escrito más recientemente". - Josh Bloch
Si está pensando en utilizar volatile
, lea el paquete java.util.concurrent
que trata sobre el comportamiento atómico.
La publicación de Wikipedia sobre un patrón Singleton muestra un uso volátil.
Volátil (vɒlətʌɪl): Se evapora fácilmente a temperaturas normales.
Punto importante sobre volatile
:
- La sincronización en Java es posible mediante el uso de palabras clave de Java
synchronized
yvolatile
bloqueos. - En Java, no podemos tener
synchronized
variables. El usosynchronized
de palabras clave con una variable es ilegal y provocará un error de compilación. En lugar de usar lasynchronized
variable en Java, puede usar lavolatile
variable java, que indicará a los subprocesos JVM que lean el valor de lavolatile
variable de la memoria principal y no lo almacenen en caché localmente. - Si una variable no se comparte entre varios subprocesos, no es necesario utilizar la
volatile
palabra clave.
fuente
Ejemplo de uso de volatile
:
public class Singleton {
private static volatile Singleton _instance; // volatile variable
public static Singleton getInstance() {
if (_instance == null) {
synchronized (Singleton.class) {
if (_instance == null)
_instance = new Singleton();
}
}
return _instance;
}
}
Estamos creando una instancia de forma perezosa en el momento en que llega la primera solicitud.
Si no creamos la _instance
variable volatile
, entonces el subproceso que está creando la instancia Singleton
no podrá comunicarse con el otro subproceso. Entonces, si el subproceso A está creando una instancia Singleton y justo después de la creación, la CPU se corrompe, etc., todos los demás subprocesos no podrán ver el valor de _instance
como no nulo y creerán que todavía está asignado como nulo.
¿Por qué pasó esto? Debido a que los subprocesos del lector no realizan ningún bloqueo y hasta que el subproceso del escritor salga de un bloque sincronizado, la memoria no se sincronizará y el valor de _instance
no se actualizará en la memoria principal. Con la palabra clave Volatile en Java, esto lo maneja el propio Java y dichas actualizaciones serán visibles para todos los hilos de lectores.
Conclusión :
volatile
la palabra clave también se utiliza para comunicar el contenido de la memoria entre subprocesos.
Ejemplo de uso de sin volátil:
public class Singleton {
private static Singleton _instance; //without volatile variable
public static Singleton getInstance() {
if (_instance == null) {
synchronized(Singleton.class) {
if (_instance == null)
_instance = new Singleton();
}
}
return _instance;
}
}
El código anterior no es seguro para subprocesos. Aunque verifica el valor de la instancia una vez más dentro del bloque sincronizado (por razones de rendimiento), el compilador JIT puede reorganizar el código de bytes de manera que la referencia a la instancia se establezca antes de que el constructor haya terminado su ejecución. Esto significa que el método getInstance() devuelve un objeto que quizás no se haya inicializado por completo. Para que el código sea seguro para subprocesos, la palabra clave volátil se puede utilizar desde Java 5 para la variable de instancia. Las variables marcadas como volátiles solo son visibles para otros subprocesos una vez que el constructor del objeto ha finalizado su ejecución por completo.
Fuente
volatile
uso en Java :
Los iteradores a prueba de fallas generalmente se implementan utilizando un volatile
contador en el objeto de lista.
- Cuando se actualiza la lista, se incrementa el contador.
- Cuando se crea un
Iterator
, el valor actual del contador se incrusta en elIterator
objeto. - Cuando
Iterator
se realiza una operación, el método compara los dos valores del contador y arroja unConcurrentModificationException
si son diferentes.
La implementación de iteradores a prueba de fallos suele ser ligera. Por lo general, se basan en propiedades de las estructuras de datos de la implementación de la lista específica. No existe un patrón general.
volatile
Es muy útil para detener hilos.
No es que debas escribir tus propios hilos, Java 1.6 tiene muchos grupos de hilos interesantes. Pero si está seguro de que necesita un hilo, necesitará saber cómo detenerlo.
El patrón que uso para los hilos es:
public class Foo extends Thread {
private volatile boolean close = false;
public void run() {
while(!close) {
// do work
}
}
public void close() {
close = true;
// interrupt here if needed
}
}
En el segmento de código anterior, el hilo que lee close
en el bucle while es diferente del que llama close()
. Sin volátil, es posible que el hilo que ejecuta el bucle nunca vea el cambio para cerrarse.
Observe cómo no hay necesidad de sincronización
Una variable declarada con volatile
palabra clave tiene dos cualidades principales que la hacen especial.
Si tenemos una variable volátil, ningún hilo puede almacenarla en caché en la memoria caché de la computadora (microprocesador). El acceso siempre se produjo desde la memoria principal.
Si hay una operación de escritura en una variable volátil y de repente se solicita una operación de lectura , se garantiza que la operación de escritura finalizará antes de la operación de lectura .
De las dos cualidades anteriores se deduce que
- Todos los hilos que lean una variable volátil definitivamente leerán el último valor. Porque ningún valor almacenado en caché puede contaminarlo. Y además, la solicitud de lectura se concederá sólo después de completar la operación de escritura actual.
Y por otro lado,
- Si investigamos más a fondo el punto 2 que he mencionado, podemos ver que
volatile
la palabra clave es una forma ideal de mantener una variable compartida que tiene 'n' número de subprocesos de lectura y solo un subproceso de escritura para acceder a ella. Una vez que agregamos lavolatile
palabra clave, listo. No hay ningún otro comentario general sobre la seguridad de los subprocesos.
Por el contrario,
No podemos utilizar volatile
palabras clave únicamente para satisfacer una variable compartida a la que más de un hilo de escritura accede a ella .