Volatile Vs Static en java

¿Es correcto decir que estático significa una copia del valor para todos los objetos y volátil significa una copia del valor para todos los hilos?

De todos modos, un valor de variable estática también va a ser un valor para todos los hilos, entonces ¿por qué deberíamos ir por volátil ?

Al declarar una variable estática en Java, significa que habrá una sola 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 una variable normal, pero es totalmente diferente de la estática . Sin embargo, incluso con los campos de Object , un hilo puede almacenar en caché un valor de variable localmente.

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

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

Sin embargo, ¡la volatilidad no es un sustituto de 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, debe implementar un locking:

 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 la clase AtomicInteger .

Diferencia entre estático y volátil:

Variable estática : si dos subprocesos (supongamos t1 y t2 ) acceden al mismo objeto y actualizan una variable que se declara como estática, significa que t1 y t2 pueden hacer su propia copia local del mismo objeto (incluidas las variables estáticas) en sus respectivas 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 t2 caché.

Las variables estáticas se usan en el contexto de Objeto donde la actualización hecha por un objeto se reflejaría en todos los otros objetos de la misma clase pero no en el contexto de Subproceso 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 t1 y t2 ) acceden al mismo objeto y actualizan una variable que se declara como volátil, significa que t1 y t2 pueden hacer su propia memoria 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á con diferentes hilos y la actualización hecha por un hilo a la variable volátil se reflejará inmediatamente en el otro Subproceso.

Además de otras respuestas, me gustaría agregar una imagen (la foto es fácil de entender)

enter image description here

static variables static se pueden almacenar en caché para hilos individuales. En el entorno de múltiples subprocesos, si un subproceso modifica sus datos almacenados en caché, es posible que no se refleje en otros subprocesos, ya que tienen una copia del mismo.

volatile statement volatile se asegura de que los subprocesos no almacenan en caché los datos y solo utiliza la copia compartida .

fuente de imagen

Creo que static y volatile no tienen ninguna relación. Le sugiero que lea el tutorial de Java para comprender el Acceso atómico , y por qué utilizar el acceso atómico, comprender qué está entrelazado , encontrará la respuesta.

En lenguaje sencillo,

  1. estático : 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 está en una ubicación fija en la memoria

  2. volátil : esta palabra clave se aplica a las variables de clase y de instancia .

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

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

enter image description here

En ausencia de palabra clave volatile , el valor de la variable en la stack de cada subproceso puede ser diferente. Al hacer que la variable sea volatile , todos los subprocesos tendrán el mismo valor en su memoria de trabajo y se evitarán los errores de coherencia de la memoria.

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

En cuanto a tu consulta:

De todos modos, un valor de variable estática también va a ser un valor para todos los hilos, entonces ¿por qué deberíamos ir por volátil?

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

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

Además, también significa que cuando un hilo lee una variable volátil, no solo ve el último cambio en el volátil, sino que los efectos secundarios del código que provocó el cambio => los errores de consistencia de la memoria aún son posibles con las variables volátiles . Para evitar los efectos secundarios, debe usar variables sincronizadas. Pero hay una mejor solución en Java.

El uso de acceso variable atómico simple es más eficiente que el acceso a estas variables a través del 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 eche un vistazo a las variables atómicas .

Preguntas relacionadas con SE:

Volatile Vs Atomic

Volatile boolean vs AtomicBoolean

Diferencia entre volátil y sincronizado en Java

el acceso volátil al valor variable será directo desde la memoria principal. Se debe usar solo en entornos de subprocesos múltiples. la variable estática se cargará una vez. Si se usa en un entorno de subproceso único, incluso si la copia de la variable se actualizará y no habrá ningún daño accediendo a ella, ya que solo hay un subproceso.

Ahora bien, si se usa una variable estática en el entorno de multi-threading, entonces habrá problemas si se espera el resultado deseado. Como cada hilo tiene su propia copia, cualquier incremento o decremento en la variable estática de un hilo puede no reflejarse en otro hilo.

si uno espera los resultados deseados de la variable estática, entonces usa volátil con estático en multihilo, entonces todo se resolverá.

Si declaramos una variable como estática, solo habrá una copia de la variable. Entonces, cada vez que diferentes subprocesos acceden 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 tomará 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 hilos.