Punto importante sobre volatile
:
- Sincronización en Java es posible mediante el uso de palabras clave de Java
synchronized
y volatile
y cerraduras.
- En Java, no podemos tener
synchronized
variables. El uso de synchronized
palabras clave con una variable es ilegal y generará un error de compilación. En lugar de usar la synchronized
variable en Java, puede usar la volatile
variable java , que le indicará a los subprocesos JVM que lean el valor de la volatile
variable de la memoria principal y no la almacenen en caché localmente.
- Si una variable no se comparte entre varios subprocesos, entonces no hay necesidad de usar la
volatile
palabra clave.
fuente
Ejemplo de uso de volatile
:
public class Singleton {
private static volatile Singleton _instance; // volatile variable
public static Singleton getInstance() {
if (_instance == null) {
synchronized (Singleton.class) {
if (_instance == null)
_instance = new Singleton();
}
}
return _instance;
}
}
Estamos creando instancia perezosamente en el momento en que llega la primera solicitud.
Si no hacemos la _instance
variable, volatile
entonces el subproceso que está creando la instancia Singleton
no puede comunicarse con el otro subproceso. Entonces, si el subproceso A está creando una instancia de Singleton y justo después de la creación, la CPU se corrompe, etc., todos los demás subprocesos no podrán ver el valor de _instance
no nulo y creerán que todavía se le asigna nulo.
¿Por qué pasó esto? Debido a que los hilos del lector no están bloqueándose y hasta que el hilo del escritor salga de un bloque sincronizado, la memoria no se sincronizará y el valor de _instance
no se actualizará en la memoria principal. Con la palabra clave Volátil en Java, esto es manejado por el propio Java y dichas actualizaciones serán visibles por todos los hilos lectores.
Conclusión : la volatile
palabra clave también se usa para comunicar el contenido de la memoria entre hilos.
Ejemplo de uso de sin volátil:
public class Singleton{
private static Singleton _instance; //without volatile variable
public static Singleton getInstance(){
if(_instance == null){
synchronized(Singleton.class){
if(_instance == null) _instance = new Singleton();
}
}
return _instance;
}
El código anterior no es seguro para subprocesos. Aunque verifica el valor de la instancia una vez más dentro del bloque sincronizado (por razones de rendimiento), el compilador JIT puede reorganizar el código de bytes de manera que la referencia a la instancia se establezca antes de que el constructor haya terminado su ejecución. Esto significa que el método getInstance () devuelve un objeto que puede no haberse inicializado por completo. Para que el código sea seguro para subprocesos, la palabra clave volátil se puede usar desde Java 5 para la variable de instancia. Las variables que están marcadas como volátiles solo son visibles para otros hilos una vez que el constructor del objeto ha finalizado su ejecución por completo.
Fuente
volatile
uso en Java :
Los iteradores de falla rápida generalmente se implementan utilizando un volatile
contador en el objeto de la lista.
- Cuando se actualiza la lista, el contador se incrementa.
- Cuando
Iterator
se crea un, el valor actual del contador se incrusta en el Iterator
objeto.
- Cuando
Iterator
se realiza una operación, el método compara los dos valores de contador y arroja un ConcurrentModificationException
si son diferentes.
La implementación de iteradores a prueba de fallos suele ser ligera. Por lo general, dependen de las propiedades de las estructuras de datos de la implementación de la lista específica. No hay un patrón general.
volatile
que vino con el nuevo modelo de memoria Java definido en JSR 133: que cuando un hilo lee unavolatile
variable, ve no solo el último valor escrito por otro hilo, sino también todos los otros escritos en otras variables que eran visibles en ese otro hilo en el momento de lavolatile
escritura. Vea esta respuesta y esta referencia .