java multithreading concurrency static volatile

Volatile vs Static en Java



multithreading concurrency (7)

Además de otras respuestas, me gustaría agregar una imagen para ella (la imagen lo hace fácil de entender)

static variables static se pueden almacenar en caché para hilos individuales En un entorno de varios subprocesos, si un subproceso modifica sus datos en caché, es posible que no se refleje en otros subprocesos, ya que tienen una copia de ellos.

volatile declaración volatile se asegura de que los subprocesos no almacenen en caché los datos y utiliza solo la copia compartida .

fuente de imagen

¿Es correcto decir que static significa una copia del valor para todos los objetos y volatile significa una copia del valor para todos los subprocesos?

De todos modos, un valor de variable static también será un valor para todos los subprocesos, entonces ¿por qué deberíamos buscar volatile ?


Creo que lo static y lo volatile no tienen relación alguna. Le sugiero que lea el tutorial de java para comprender el acceso atómico y, por qué utilizar el acceso atómico, entienda qué está interleaved , encontrará la respuesta.


Declarar una variable estática 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 creados en absoluto. Sin embargo, los subprocesos pueden tener valores almacenados en caché localmente

Cuando una variable es volátil y no estática , habrá una variable para cada Object . Entonces, en la superficie parece que no hay diferencia con respecto a una variable normal pero totalmente diferente de la estática . Sin embargo, incluso con los campos Object , un hilo puede almacenar en caché un valor variable localmente.

Esto significa que si dos subprocesos actualizan una variable del mismo Objeto simultáneamente, y la variable no se declara volátil, podría darse el caso de que uno de los subprocesos tenga en la caché un valor antiguo.

¡Incluso si accede a un valor estático a través de múltiples subprocesos, cada subproceso puede tener su copia local en caché! Para evitar esto, puede declarar la variable como estática volátil y esto forzará al hilo a leer cada vez el valor global.

Sin embargo, ¡ volatile no es un sustituto para la sincronización correcta!
Por ejemplo:

private static volatile int counter = 0; private void concurrentMethodWrong() { counter = counter + 5; //do something counter = counter - 5; }

¡Ejecutar concurrentMethodWrong concurrentemente muchas veces puede llevar a un valor final de contador diferente de cero!
Para resolver el problema, tienes que 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 use la clase AtomicInteger .


Diferencia entre estática y volátil:

Variable estática : si dos subprocesos (suponga que t1 y t2 ) acceden al mismo objeto y actualizan una variable declarada como estática, significa que t1 y t2 pueden hacer su propia copia local del mismo objeto (incluidas las variables estáticas) en sus respectivos caché, por lo que la actualización realizada por t1 a la variable estática en su caché local no se reflejará en la variable estática para el caché t2 .

Las variables estáticas se utilizan en el contexto de 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 Hilo donde la actualización de un subproceso a la variable estática reflejará los cambios inmediatamente a todos los hilos (en su caché local).

Variable volátil : si dos subprocesos (supongamos que t1 y t2 ) acceden al mismo objeto y actualizan una variable que se declara como volátil, significa que t1 y t2 pueden crear su propio caché local del objeto, excepto la variable que se declara como volátil. . Por lo tanto, la variable volátil tendrá solo una copia principal que se actualizará mediante diferentes subprocesos y la actualización realizada por un subproceso a la variable volátil se reflejará inmediatamente en el otro subproceso.


El acceso a valores variables volátiles será directo desde la memoria principal. Se debe utilizar solo en entornos de subprocesos múltiples. La variable estática se cargará una vez. Si se usa en un solo entorno de subprocesos, incluso si la copia de la variable se actualizará y no habrá ningún daño al acceder a ella, ya que solo hay un subproceso.

Ahora, si la variable estática se usa en un entorno de subprocesos múltiples, habrá problemas si uno espera el resultado deseado. Como cada subproceso tiene su propia copia, entonces cualquier incremento o disminución en la variable estática de un subproceso puede no reflejarse en otro subproceso.

Si uno espera los resultados deseados de la variable estática, use volatile with static en multi-threading, entonces todo se resolverá.


En lenguaje sencillo,

  1. static : las variables static están asociadas con la clase , en lugar de con cualquier objeto . Cada instancia de la clase comparte una variable de clase, que se encuentra en una ubicación fija en la memoria

  2. volatile : esta palabra clave es aplicable a las variables de clase y de instancia .

El uso de variables volátiles reduce el riesgo de errores de consistencia de la memoria, porque cualquier escritura en una variable volátil establece una relación de suceso antes con lecturas posteriores de esa misma variable. Esto significa que los cambios en una variable volátil siempre son visibles para otros subprocesos

Eche un vistazo a este article de Javin Paul para comprender las variables volátiles de una mejor manera.

En ausencia de una palabra clave volatile , el valor de la variable en la pila de cada hilo puede ser diferente. Al hacer que la variable sea volatile , todos los subprocesos obtendrán el mismo valor en su memoria de trabajo y se evitarán los errores de consistencia de la memoria.

Aquí el término variable puede ser una variable static (clase) o una variable instance (objeto).

Respecto a su consulta:

De todos modos, un valor de variable estática también será un valor para todos los subprocesos, entonces ¿por qué deberíamos buscar volátiles?

Si necesito una variable de instance en mi aplicación, no puedo usar una variable static . Incluso en el caso de una variable static , la consistencia no está garantizada debido a la memoria caché de subprocesos como se muestra en el diagrama.

El uso de variables volatile reduce el riesgo de errores de consistencia de la memoria, porque cualquier escritura en una variable volátil establece una relación de suceso antes con lecturas posteriores de esa misma variable. Esto significa que los cambios en una variable volátil siempre son visibles para otros subprocesos.

Lo que es más, también significa que cuando un hilo lee una variable volátil, no solo ve el último cambio en la volatilidad, sino también los efectos secundarios del código que provocó el cambio => errores de coherencia de memoria son todavía posibles con variables volátiles . Para evitar efectos secundarios, tienes que usar variables sincronizadas. Pero hay una mejor solución en java.

El uso de un simple acceso a variables atómicas es más eficiente que acceder a estas variables a través de un código sincronizado

Algunas de las clases en el paquete java.util.concurrent proporcionan métodos atómicos que no dependen de la sincronización.

Consulte este artículo de control de concurrencia de alto nivel para obtener más detalles.

Especialmente echar un vistazo a las variables atómicas .

Preguntas de SE relacionadas:

Vs volátil atómico

Volatile boolean vs atomic boolean

Diferencia entre lo volátil y lo sincronizado en Java.


Si declaramos una variable como estática, solo habrá una copia de la variable. Por lo tanto, cuando diferentes subprocesos accedan a esa variable, solo habrá un valor final para la variable (ya que solo hay una ubicación de memoria asignada para la variable).

Si una variable se declara como volátil, todos los subprocesos tendrán su propia copia de la variable, pero el valor se toma de la memoria principal. Por lo tanto, el valor de la variable en todos los subprocesos será el mismo.

Entonces, en ambos casos, el punto principal es que el valor de la variable es el mismo en todos los subprocesos.