volatile
tiene semántica para visibilidad de memoria. Básicamente, el valor de un volatile
campo se vuelve visible para todos los lectores (otros hilos en particular) después de que se completa una operación de escritura. Sin ellos volatile
, los lectores podrían ver algún valor no actualizado.
Para responder a su pregunta: Sí, uso una volatile
variable para controlar si algún código continúa un bucle. El bucle prueba el volatile
valor y continúa si es así true
. La condición se puede establecer false
llamando a un método de "detención". El bucle ve false
y termina cuando prueba el valor después de que el método de detención completa la ejecución.
El libro " Concurrencia de Java en la práctica ", que recomiendo encarecidamente, ofrece una buena explicación volatile
. Este libro está escrito por la misma persona que escribió el artículo de IBM al que se hace referencia en la pregunta (de hecho, cita su libro al final de ese artículo). Mi uso de volatile
es lo que su artículo llama la "bandera de estado del patrón 1".
Si desea obtener más información acerca de cómo volatile
funciona bajo el capó, lea sobre el modelo de memoria Java . Si desea ir más allá de ese nivel, consulte un buen libro de arquitectura de computadoras como Hennessy & Patterson y lea sobre la coherencia y coherencia de la memoria caché.
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 ."... el modificador volátil garantiza que cualquier hilo que lea un campo verá el valor escrito más recientemente". - Josh Bloch
Si está pensando en usar
volatile
, lea el paquetejava.util.concurrent
que trata sobre el comportamiento atómico.La publicación de Wikipedia sobre un patrón Singleton muestra un uso volátil.
fuente
volatile
ysynchronized
palabras clave?volatile
ejemplo. Se puede encontrar en una versión archivada .void
ypublic
palabras clave".Punto importante sobre
volatile
:synchronized
yvolatile
y cerraduras.synchronized
variables. El uso desynchronized
palabras clave con una variable es ilegal y generará un error de compilación. En lugar de usar lasynchronized
variable en Java, puede usar lavolatile
variable java , que le indicará a los subprocesos JVM que lean el valor de lavolatile
variable de la memoria principal y no la almacenen en caché localmente.volatile
palabra clave.fuente
Ejemplo de uso de
volatile
: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 instanciaSingleton
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.Ejemplo de uso de sin volátil:
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.Iterator
se crea un, el valor actual del contador se incrusta en elIterator
objeto.Iterator
se realiza una operación, el método compara los dos valores de contador y arroja unConcurrentModificationException
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.
fuente
private static final Singleton _instance;
también.volatile
Es muy útil para detener hilos.No es que deba escribir sus propios hilos, Java 1.6 tiene muchos grupos de hilos agradables. Pero si está seguro de que necesita un hilo, necesitará saber cómo detenerlo.
El patrón que uso para hilos es:
En el segmento de código anterior, la lectura del hilo
close
en el bucle while es diferente de la que llamaclose()
. Sin volátil, es posible que el subproceso que ejecuta el bucle nunca vea el cambio para cerrar.Observe cómo no hay necesidad de sincronización
fuente
volatile
palabra clave, y siempre parece funcionar bien.Un ejemplo común para usar
volatile
es usar unavolatile boolean
variable como una bandera para terminar un hilo. Si ha comenzado un hilo, y desea poder interrumpirlo de manera segura desde un hilo diferente, puede hacer que el hilo verifique periódicamente una bandera. Para detenerlo, establezca la bandera en verdadero. Al hacer el indicadorvolatile
, puede asegurarse de que el subproceso que lo está comprobando verá que se ha establecido la próxima vez que lo verifique sin tener que usar unsynchronized
bloque.fuente
Una variable declarada con
volatile
palabra clave, tiene dos cualidades principales que la hacen especial.Si tenemos una variable volátil, ningún hilo puede almacenarla en la memoria caché de la computadora (microprocesador). El acceso siempre ocurrió desde la memoria principal.
Si hay una operación de escritura en una variable volátil, y de repente se solicita una operación de lectura , se garantiza que la operación de escritura finalizará antes de la operación de lectura .
Dos cualidades anteriores deducen que
Y por otro lado,
volatile
palabra clave es una forma ideal de mantener una variable compartida que tiene 'n' número de hilos de lectura y solo un hilo de escritor para acceder a ella. Una vez que agreguemos lavolatile
palabra clave, ya está. No hay otros gastos generales sobre la seguridad del hilo.Por el contrario,
No podemos hacer uso de la
volatile
palabra clave únicamente, para satisfacer una variable compartida que tiene más de un hilo de escritor que accede a ella .fuente
Nadie ha mencionado el tratamiento de la operación de lectura y escritura para el tipo variable largo y doble. Las lecturas y escrituras son operaciones atómicas para variables de referencia y para la mayoría de las variables primitivas, excepto los tipos de variables largas y dobles, que deben usar la palabra clave volátil para ser operaciones atómicas. @enlace
fuente
Sí, debe usarse volátil siempre que desee que varios subprocesos accedan a una variable mutable. No es un caso de uso muy común porque, por lo general, debe realizar más de una operación atómica (por ejemplo, verificar el estado variable antes de modificarlo), en cuyo caso utilizaría un bloque sincronizado.
fuente
En mi opinión, dos escenarios importantes además de detener el hilo en el que se usa la palabra clave volátil son:
fuente
Deberá usar una palabra clave 'volátil' o 'sincronizada' y cualquier otra herramienta y técnica de control de concurrencia que pueda tener a su disposición si está desarrollando una aplicación multiproceso. Ejemplo de dicha aplicación son las aplicaciones de escritorio.
Si está desarrollando una aplicación que se implementaría en el servidor de aplicaciones (Tomcat, JBoss AS, Glassfish, etc.), no tiene que manejar el control de concurrencia usted mismo, ya que el servidor de aplicaciones ya lo ha abordado. De hecho, si recordaba correctamente, el estándar Java EE prohíbe cualquier control de concurrencia en servlets y EJB, ya que es parte de la capa de 'infraestructura' que se supone que está libre de manejar. Solo realiza el control de concurrencia en dicha aplicación si implementa objetos singleton. Esto incluso ya se solucionó si teje sus componentes usando frameworkd como Spring.
Por lo tanto, en la mayoría de los casos de desarrollo de Java donde la aplicación es una aplicación web y usa el marco de trabajo IoC como Spring o EJB, no necesitaría usar 'volátil'.
fuente
volatile
solo garantiza que todos los hilos, incluso ellos mismos, estén incrementándose. Por ejemplo: un contador ve la misma cara de la variable al mismo tiempo. No se usa en lugar de sincronizado o atómico u otras cosas, sincroniza completamente las lecturas. No lo compare con otras palabras clave de Java. Como el ejemplo muestra a continuación, las operaciones de variables volátiles también son atómicas, fallan o tienen éxito a la vez.Incluso si pones resultados volátiles o no, siempre serán diferentes. Pero si usa AtomicInteger como se muestra a continuación, los resultados serán siempre los mismos. Esto es lo mismo con sincronizado también.
fuente
Sí, lo uso bastante, puede ser muy útil para código multiproceso. El artículo al que apuntaste es bueno. Aunque hay dos cosas importantes a tener en cuenta:
fuente
Cada hilo que acceda a un campo volátil leerá su valor actual antes de continuar, en lugar de (potencialmente) usar un valor almacenado en caché.
Solo la variable miembro puede ser volátil o transitoria.
fuente
Absolutamente sí. (Y no solo en Java, sino también en C #). Hay momentos en los que necesita obtener o establecer un valor que garantice que sea una operación atómica en su plataforma dada, un int o booleano, por ejemplo, pero no requiere la sobrecarga de bloqueo de hilo. La palabra clave volátil le permite asegurarse de que cuando lea el valor obtenga el valor actual y no un valor almacenado en caché que acaba de quedar obsoleto por una escritura en otro hilo.
fuente
Hay dos usos diferentes de la palabra clave volátil.
Se utiliza un indicador de ocupado para evitar que un subproceso continúe mientras el dispositivo está ocupado y el indicador no está protegido por un bloqueo:
El hilo de prueba continuará cuando otro hilo apague la bandera de ocupado :
Sin embargo, dado que se accede con frecuencia a ocupado en el subproceso de prueba, la JVM puede optimizar la prueba colocando el valor de ocupado en un registro, luego probar el contenido del registro sin leer el valor de ocupado en la memoria antes de cada prueba. El subproceso de prueba nunca vería un cambio ocupado y el otro subproceso solo cambiaría el valor de ocupado en la memoria, lo que da como resultado un punto muerto. Declarar el indicador de ocupado como volátil obliga a leer su valor antes de cada prueba.
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 "sucede antes" con lecturas posteriores de esa misma variable. Esto significa que los cambios en una variable volátil siempre son visibles para otros subprocesos.
La técnica de lectura, escritura sin errores de consistencia de memoria se llama acción atómica .
Una acción atómica es aquella que efectivamente ocurre de una vez. Una acción atómica no puede detenerse en el medio: sucede completamente o no sucede en absoluto. No se ven los efectos secundarios de una acción atómica hasta que se complete la acción.
A continuación hay acciones que puede especificar que son atómicas:
¡Salud!
fuente
volatile
dice para un programador que el valor siempre estará actualizado. El problema es que el valor se puede guardar en diferentes tipos de memoria de hardware. Por ejemplo, pueden ser registros de CPU, caché de CPU, RAM ... Los registros de CPU y caché de CPU pertenecen a la CPU y no pueden compartir datos a diferencia de la RAM que está en el rescate en un entorno de subprocesos múltiples.volatile
La palabra clave dice que una variable será leída y escrita directamente desde / hacia la memoria RAM . Tiene alguna huella de cálculoJava 5
extendidovolatile
apoyandohappens-before
[Acerca de]volatile
La palabra clave no cura unarace condition
situación en la que varios hilos pueden escribir algunos valores simultáneamente. La respuesta es lasynchronized
palabra clave [Acerca de]Como resultado, es seguro solo cuando un hilo escribe y otros simplemente leen el
volatile
valorvolátil vs sincronizado
fuente
Volátil hace lo siguiente.
1> La lectura y escritura de variables volátiles por diferentes subprocesos siempre se realiza desde la memoria, no desde la propia caché o registro de la CPU. Por lo tanto, cada hilo siempre trata con el último valor. 2> Cuando 2 subprocesos diferentes funcionan con la misma instancia o variables estáticas en el montón, uno puede ver las acciones de otros como fuera de orden. Vea el blog de jeremy manson sobre esto. Pero la volatilidad ayuda aquí.
El siguiente código en ejecución completa muestra cómo se pueden ejecutar varios subprocesos en un orden predefinido y resultados de impresión sin usar palabras clave sincronizadas.
Para lograr esto, podemos usar el siguiente código de ejecución completo.
El siguiente enlace de github tiene un archivo Léame, que proporciona una explicación adecuada. https://github.com/sankar4git/volatile_thread_ordering
fuente
Desde la página de documentación de Oracle , surge la necesidad de variables volátiles para solucionar problemas de consistencia de memoria:
Esto significa que los cambios en una
volatile
variable siempre son visibles para otros subprocesos. También significa que cuando un hilo lee una variable volátil, ve no solo el último cambio en elvolatile
, sino también los efectos secundarios del código que provocó el cambio.Como se explicó en la
Peter Parker
respuesta, en ausencia de unvolatile
modificador, la pila de cada subproceso puede tener su propia copia de la variable. Al hacer la variable comovolatile
, se han solucionado los problemas de consistencia de memoria.Eche un vistazo a la página del tutorial de jenkov para una mejor comprensión.
Eche un vistazo a la pregunta SE relacionada para obtener más detalles sobre volátiles y casos de uso para usar volátiles:
Diferencia entre volátil y sincronizado en Java
Un caso de uso práctico:
Usted tiene muchos hilos, que necesitan imprimir la hora actual en un formato determinado, por ejemplo:
java.text.SimpleDateFormat("HH-mm-ss")
. Yon puede tener una clase, que convierte la hora actualSimpleDateFormat
y actualiza la variable por cada segundo. Todos los otros hilos pueden simplemente usar esta variable volátil para imprimir la hora actual en archivos de registro.fuente
Las variables volátiles son sincronización ligera. Cuando la visibilidad de los últimos datos entre todos los subprocesos es un requisito y la atomicidad puede verse comprometida, en tales situaciones se deben preferir las variables volátiles. La lectura de variables volátiles siempre devuelve la escritura más reciente realizada por cualquier subproceso ya que no se almacenan en caché en registros ni en cachés donde otros procesadores no pueden ver. Volátil es sin bloqueo. Yo uso volátil, cuando el escenario cumple con los criterios mencionados anteriormente.
fuente
La tecla volátil cuando se usa con una variable, se asegurará de que los hilos que lean esta variable vean el mismo valor. Ahora, si tiene varios hilos que leen y escriben en una variable, hacer que la variable sea volátil no será suficiente y los datos se corromperán. Los subprocesos de imagen han leído el mismo valor, pero cada uno ha realizado algunos cambios (por ejemplo, incrementó un contador), al volver a escribir en la memoria, se viola la integridad de los datos. Es por eso que es necesario sincronizar la variable (son posibles diferentes formas)
Si los cambios se realizan con 1 subproceso y los demás solo necesitan leer este valor, el volátil será adecuado.
fuente
La variable volátil se usa básicamente para la actualización instantánea (vaciado) en la línea principal de caché compartida una vez que se actualiza, para que los cambios se reflejen en todos los subprocesos de trabajo de inmediato.
fuente
A continuación se muestra un código muy simple para demostrar el requisito de
volatile
variable que se utiliza para controlar la ejecución de Thread desde otro thread (este es un escenario dondevolatile
se requiere).Cuando
volatile
no se usa: nunca verá el mensaje ' Detenido el: xxx ' incluso después de ' Detener el: xxx ', y el programa continúa ejecutándose.Cuando se
volatile
usa: verá el mensaje ' Detenido el: xxx ' inmediatamente.Demostración: https://repl.it/repls/SilverAgonizingObjectcode
fuente