java multithreading thread-safety volatile

transient java



¿Es un int volatile en Java thread-safe? (6)

¿Es un int volatile en Java thread-safe? Es decir, ¿se puede leer y escribir de forma segura sin bloqueo?


[...] como para poder leer y escribir de forma segura sin bloquear?

Sí, una lectura siempre dará como resultado el valor de la última escritura, (y tanto las lecturas como las escrituras son operaciones atómicas).

Una lectura / escritura volátil introduce una llamada relación de pasar antes en la ejecución.

De la Especificación de Lenguaje Java Capítulo 17: Hilos y Cerraduras

Una escritura en un campo volátil (§8.3.1.4) ocurre, antes de cada lectura posterior de ese campo.

En otras palabras, cuando se trata de variables volátiles, no tiene que sincronizar explícitamente (introducir una relación de pase antes) usando synchronized palabra clave synchronized para asegurarse de que el hilo obtenga el último valor escrito en la variable.

Sin embargo, como señala Jon Skeet, el uso de variables volátiles es limitado, y en general debería considerar usar clases del paquete java.util.concurrent .


1) Si dos hilos están leyendo y escribiendo en una variable compartida, entonces usar la palabra clave volátil no es suficiente. Debe usar un sincronizado en ese caso para garantizar que la lectura y escritura de la variable sea atómica. Leer o escribir una variable volátil no bloquea los hilos de lectura o escritura. Para que esto suceda, debe usar la palabra clave sincronizada alrededor de las secciones críticas.

2) Como alternativa a un bloque sincronizado, también puede usar uno de los muchos tipos de datos atómicos que se encuentran en el paquete java.util.concurrent. Por ejemplo, AtomicLong o AtomicReference o uno de los otros.

Es seguro para subprocesos si tiene un subproceso de escritor y varios subprocesos de lector.

class Foo { private volatile Helper helper = null; public Helper getHelper() { if (helper == null) { synchronized(this) { if (helper == null) helper = new Helper(); } } return helper; } }

Nota: Si el ayudante es inmutable, entonces no hay necesidad de palabra clave volátil. Aquí el singleton funcionará correctamente.

En el caso del contador que se incrementa por varios hilos (operación de escritura de lectura) no dará la respuesta correcta. Esta condición también se ilustra por la condición de raza.

public class Counter{ private volatile int i; public int increment(){ i++; } }

NOTA: Aquí volátil no ayudará.


El acceso a volatile int en Java será seguro para subprocesos. Cuando digo acceso me refiero a la operación de la unidad sobre él, como volatile_var = 10 o int temp = volatile_var (básicamente escribir / leer con valores constantes). La palabra clave volátil en Java garantiza dos cosas:

  1. Cuando lee, siempre obtiene el valor en la memoria principal. En general, para fines de optimización, la JVM utiliza registros o, en términos más generales, variables de almacenamiento / acceso de la memoria local . Por lo tanto, en un entorno de subprocesos múltiples, cada subproceso puede ver una copia diferente de la variable. Pero volviéndolo volátil asegura que la variable write to variable se vacíe en la memoria principal y que también se lea en la memoria principal y, por lo tanto, asegúrese de que el hilo vea la copia correcta de la variable.
  2. El acceso al volátil se sincroniza automáticamente. Entonces, JVM asegura un orden mientras lee / escribe en la variable.

Sin embargo, Jon Skeet menciona correctamente que en operaciones no atómicas (volatile_var = volátil + 1) diferentes hilos pueden obtener resultados inesperados.


No siempre.

No es seguro para subprocesos si hay varios hilos escribiendo y leyendo la variable. Es seguro para subprocesos si tiene un subproceso de escritor y varios subprocesos de lector.

Si está buscando hilo de manera segura, use AtomicXXX clases AtomicXXX

Un pequeño conjunto de herramientas de clases que admiten la programación sin bloqueo de subprocesos en variables individuales.

En esencia, las clases de este paquete extienden la noción de valores volátiles, campos y elementos de matriz a aquellos que también proporcionan una operación de actualización condicional atómica del formulario:

boolean compareAndSet(expectedValue, updateValue);

Consulte @te para responder en la siguiente publicación:

Volatile boolean vs AtomicBoolean


Sí, puede leer y escribir de forma segura, pero no puede hacer nada compuesto, como aumentarlo de forma segura, ya que es un ciclo de lectura / modificación / escritura. También está la cuestión de cómo interactúa con el acceso a otras variables.

La naturaleza precisa de la volatilidad es francamente confusa (ver la sección de modelo de memoria de la JLS para más detalles ). Personalmente, en general usaría AtomicInteger como una forma más sencilla de asegurarme de que lo hago bien.


Si un elemento volátil no depende de ninguna otra variable volátil, su hilo es seguro para la operación de lectura. En caso de escritura volátil no garantiza la seguridad del hilo.

Supongamos que tiene una variable i que es volátil y su valor depende de otra variable volátil como j. Ahora la variable de acceso Thread-1 j la incrementa y está a punto de actualizarla en la memoria principal desde la memoria caché de la CPU. En caso de que el Thread-2 lea el
la variable i antes de que Thread-1 realmente pueda actualizar j en la memoria principal. El valor de i será según el valor antiguo de j, que sería incorrecto. También se llama Dirty read.