Solución:
Declarando un estático variable en Java, significa que solo habrá una copia, sin importar cuántos objetos de la clase se creen. La variable será accesible incluso sin Objects
creado en absoluto. Sin embargo, los subprocesos pueden tener valores almacenados en caché localmente.
Cuando una variable es volátil y no estático, habrá una variable para cada Object
. Entonces, en la superficie, parece que no hay diferencia con una variable normal, pero es totalmente diferente de estático. Sin embargo, incluso con Object
campos, un hilo puede almacenar en caché un valor de variable localmente.
Esto significa que si dos subprocesos actualizan una variable del mismo Objeto al mismo tiempo, y la variable no se declara volátil, podría darse el caso de que uno de los subprocesos tenga en caché un valor antiguo.
Incluso si accede a un estático valor a través de varios subprocesos, ¡cada subproceso puede tener su copia en caché local! Para evitar esto, puede declarar la variable como estático volátil y esto obligará al hilo a leer cada vez el valor global.
Sin embargo, volátil no es un sustituto de la sincronización adecuada.
Por ejemplo:
private static volatile int counter = 0;
private void concurrentMethodWrong() {
counter = counter + 5;
//do something
counter = counter - 5;
}
Ejecutando concurrentMethodWrong
concurrentemente muchas veces puede conducir a un valor final de contador diferente de cero!
Para resolver el problema, debe implementar un bloqueo:
private static final Object counterLock = new Object();
private static volatile int counter = 0;
private void concurrentMethodRight() {
synchronized (counterLock) {
counter = counter + 5;
}
//do something
synchronized (counterLock) {
counter = counter - 5;
}
}
O usa el AtomicInteger
clase.
Diferencia entre estático y volátil:
Variable estática: Si dos subprocesos (suponga t1
y t2
) están accediendo al mismo objeto y actualizando una variable que se declara como estática, entonces significa t1
y t2
puede hacer su propia copia local del mismo objeto (incluidas las variables estáticas) en su respectiva caché, por lo que la actualización la realiza t1
a la variable estática en su caché local no se reflejará en la variable estática para t2
caché.
Las variables estticas se utilizan en el contexto del objeto donde la actualización realizada por un objeto se reflejaría en todos los demás objetos de la misma clase pero no en el contexto de Thread donde la actualización de un hilo a la variable estática reflejará los cambios inmediatamente en todos los hilos (en su caché local).
Variable volátil: Si dos subprocesos (suponga t1
y t2
) están accediendo al mismo objeto y actualizando una variable que se declara como volátil, entonces significa t1
y t2
puede hacer su propia caché local del Objeto excepto la variable que se declara como volátil . Entonces, la variable volátil tendrá solo una copia principal que será actualizada por diferentes subprocesos y la actualización realizada por un subproceso a la variable volátil se reflejará inmediatamente en el otro subproceso.
Además de otras respuestas, me gustaría agregar una imagen (la imagen hace que sea fácil de entender)
static
las variables se pueden almacenar en caché para subprocesos individuales. En un entorno de subprocesos múltiples si un subproceso modifica sus datos en caché, es posible que no se refleje en otros subprocesos, ya que tienen una copia de ella.
volatile
declaración asegura que los hilos no almacena en caché los datos y usa la copia compartida solamente.
fuente de imagen