¿Qué significa "volátil" en Java?
volatile java-memory-model (5)
Usamos volatile
en uno de nuestros proyectos para mantener la misma copia de variable a la que acceden diferentes hilos. Mi pregunta es si está bien usar volatile
with static
. El compilador no da ningún error pero no entiendo la razón de usar ambos.
Aparte de leer la especificación del modelo de memoria, te recomiendo que leas http://jeremymanson.blogspot.com/2008/11/what-volatile-means-in-java.html . Está escrito por uno de los autores de JMM y debe responder a su pregunta. Pensar en la memoria lee y escribe en términos de la cláusula de suceso happens-before también es útil; el JMM para Java 5 en adelante agrega semántica de volatile
antes que volatile
.
Específicamente, cuando lee una variable volátil de un hilo, todas las escrituras hasta e incluyendo la escritura en esa variable volátil de otros hilos ahora son visibles para ese hilo. Si tiene algo de tiempo, hay una charla sobre tecnología de Google que trata más a fondo el tema: https://code.google.com/edu/languages/#_java_memmodel .
Y, sí, puedes usar static
con volatile
. Ellos hacen cosas diferentes.
Considere un escenario cuando dos subprocesos (Thread1 y Thread2) acceden a la misma variable ''mObject'' con valor 1.
cuando se ejecuta un Thread1, no espera que otros subprocesos modifiquen la variable ''mObject''. En este escenario, Thread1 almacena en caché la variable ''mObject'' con valor 1.
Y si Thread2 modifica el valor de ''mObject'' a 2, aún Thread1 estaría refiriendo el valor de mObject como 1 ya que hizo el almacenamiento en caché. Para evitar este almacenamiento en caché debemos declarar la variable como
mObjeto int volátil privado;
en este escenario, Thread1 obtendrá el valor actualizado de mObject
En Java, volatile tiene un significado general similar al de C. El modelo de memoria de Java (consulte el excelente enlace en la respuesta de ide) permite que los hilos "vean" un valor diferente al mismo tiempo para las variables marcadas como no volátiles. Por ejemplo:
Hilo a:
n = 1;
// wait...
n = 2;
Hilos B y C:
while (true) {
System.out.println(name + ": " + n);
}
Se permite que ocurra esta salida (tenga en cuenta que no se garantiza que se alterne estrictamente entre B y C, solo estoy tratando de mostrar el "cambio" de B y C aquí):
C: 1
B: 1
C: 2
B: 1
C: 2
B: 2
Esto es completamente separado de la cerradura tomada por println
; se permite que el subproceso B vea n
como 1 incluso después de que C descubra que es 2. Existe una variedad de muy buenas razones para esto que no puedo pretender comprender completamente, muchas de ellas relacionadas con la velocidad y otras relacionadas con la seguridad.
Si es volátil, tiene la garantía (aparte del bloqueo de println
, que ignoraré por el momento) de que B y C verán "simultáneamente" el nuevo valor de B tan pronto como se envíe.
Puedes usar volatile
with static
porque afectan diferentes cosas. volatile
causa que una variable se "replique" en todos los subprocesos que usan esa variable antes de usarla, mientras que la static
comparte una única variable entre todas las clases que usan esa variable. (Esto puede ser bastante confuso para las personas nuevas en los subprocesos en Java, porque cada Thread
se implementa como una class
).
La volatilidad se usa en muchas situaciones diferentes en las que múltiples hilos necesitan acceso a la misma variable. Muchas personas que no realizan programación multihilo / concurrente no estarían expuestas a esto. La volatilidad garantiza que la variable siempre se lea desde la memoria principal y no desde una versión de caché / registro. Lo volátil no es en sí mismo un bloqueo, solo porque los cambios son vistos por todos los subprocesos tan pronto como se escriben, no significa que pueda compararse e intercambiarse de forma atómica. Sin embargo, esta característica se puede usar con otras características, como comparar e intercambiar para construir estructuras de datos que sean seguras para subprocesos sin necesidad de que el usuario de la semántica de notificación de espera de java sea más "pesado".
puede obtener más información en este enlace http://www.quora.com/Threading-in-Java/What-is-the-purpose-of-the-volatile-keyword-in-java
volatile
significa que la variable cambia en tiempo de ejecución y que el compilador no debe almacenar su valor en caché por ningún motivo.
Esto solo es realmente un problema al compartir la variable entre subprocesos, no desea que un subproceso funcione con datos obsoletos, por lo que el compilador nunca debe almacenar en caché el valor de una referencia de variable volatile
.