¿Para qué es útil la palabra clave volátil?


672

En el trabajo de hoy, me encontré con la volatilepalabra clave en Java. Al no estar muy familiarizado con esto, encontré esta explicación:

Teoría y práctica de Java: gestión de la volatilidad

Dado el detalle en el que ese artículo explica la palabra clave en cuestión, ¿alguna vez la usó o podría ver un caso en el que podría usar esta palabra clave de la manera correcta?

Respuestas:


742

volatiletiene semántica para visibilidad de memoria. Básicamente, el valor de un volatilecampo 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 volatilevariable para controlar si algún código continúa un bucle. El bucle prueba el volatilevalor y continúa si es así true. La condición se puede establecer falsellamando a un método de "detención". El bucle ve falsey 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 volatilees 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 volatilefunciona 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é.


118
Esta respuesta es correcta, pero incompleta. Omite una propiedad importante volatileque vino con el nuevo modelo de memoria Java definido en JSR 133: que cuando un hilo lee una volatilevariable, 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 la volatileescritura. Vea esta respuesta y esta referencia .
Adam Zalcman

46
Para los principiantes, le pediría que hiciera una demostración con algún código (¿por favor?)
Hungry Blue Dev

66
El artículo vinculado en la pregunta tiene ejemplos de código.
Greg Mattes

Creo que el enlace 'Hennessy & Patterson' está roto. Y el enlace al 'modelo de memoria Java' en realidad conduce a la Especificación del lenguaje Java de Oracle 'Capítulo 17. Hilos y bloqueos'.
Kris

2
@fefrei: "inmediatamente" es un término coloquial. Por supuesto, eso no puede garantizarse cuando ni el tiempo de ejecución ni los algoritmos de programación de subprocesos están realmente especificados. La única forma para que un programa descubra si una lectura volátil es posterior a una escritura volátil particular, es verificando si el valor visto es el esperado escrito.
Holger

177

"... 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 paquete java.util.concurrentque trata sobre el comportamiento atómico.

La publicación de Wikipedia sobre un patrón Singleton muestra un uso volátil.


18
¿Por qué hay ambas volatiley synchronizedpalabras clave?
ptkato

55
El artículo de Wikipedia sobre un patrón Singleton ha cambiado mucho desde entonces y ya no presenta dicho volatileejemplo. Se puede encontrar en una versión archivada .
bskp

1
@ptkato Estas dos palabras clave tienen propósitos completamente diferentes, por lo que la pregunta no tiene mucho sentido como comparación, aunque ambas están relacionadas con la concurrencia. Es como decir "¿Por qué hay ambas voidy publicpalabras clave".
DavidS

134

Punto importante sobre volatile:

  1. Sincronización en Java es posible mediante el uso de palabras clave de Java synchronizedy volatiley cerraduras.
  2. En Java, no podemos tener synchronizedvariables. El uso de synchronizedpalabras clave con una variable es ilegal y generará un error de compilación. En lugar de usar la synchronizedvariable en Java, puede usar la volatilevariable java , que le indicará a los subprocesos JVM que lean el valor de la volatilevariable de la memoria principal y no la almacenen en caché localmente.
  3. Si una variable no se comparte entre varios subprocesos, entonces no hay necesidad de usar la volatilepalabra 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 _instancevariable, volatileentonces el subproceso que está creando la instancia Singletonno 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 _instanceno 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 _instanceno 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 volatilepalabra 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

ingrese la descripción de la imagen aquí

volatileuso en Java :

Los iteradores de falla rápida generalmente se implementan utilizando un volatilecontador en el objeto de la lista.

  • Cuando se actualiza la lista, el contador se incrementa.
  • Cuando Iteratorse crea un, el valor actual del contador se incrusta en el Iteratorobjeto.
  • Cuando Iteratorse realiza una operación, el método compara los dos valores de contador y arroja un ConcurrentModificationExceptionsi 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.


2
"Los iteradores a prueba de fallas generalmente se implementan usando un contador volátil" - ya no es el caso, demasiado costoso: bugs.java.com/bugdatabase/view_bug.do?bug_id=6625725
Vsevolod Golovanov

¿son seguras las comprobaciones dobles de _instance? pensé que no son seguros incluso con volátiles
Dexters

"que indicará a los subprocesos JVM que lean el valor de la variable volátil de la memoria principal y no lo almacenen en caché localmente". buen punto
Humoyun Ahmad

Para la seguridad del hilo, uno podría ir private static final Singleton _instance;también.
Chris311

53

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:

public class Foo extends Thread {

  private volatile boolean close = false;

  public void run() {
    while(!close) {
      // do work
    }
  }
  public void close() {
    close = true;
    // interrupt here if needed
  }
}

En el segmento de código anterior, la lectura del hilo closeen el bucle while es diferente de la que llama close(). 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


2
Me pregunto por qué eso es incluso necesario. ¿No es eso solo necesario si otros hilos tienen que reaccionar ante el cambio de estado de este hilo de tal manera que la sincronización de los hilos esté en peligro?
Jori

27
@Jori, necesitas volátil porque la lectura de hilo cerca en el ciclo while es diferente de la que llama close (). Sin volátil, es posible que el subproceso que ejecuta el bucle nunca vea el cambio para cerrar.
Pirolístico

¿Diría que hay una ventaja entre detener un hilo así o usar los métodos Thread # interrupt () y Thread # isInterrupted ()?
Ricardo Belchior

2
@Pyrolistical - ¿Has observado el hilo sin ver el cambio en la práctica? ¿O puede extender el ejemplo para desencadenar ese problema de manera confiable? Tengo curiosidad porque sé que he usado (y he visto a otros usar) código que es básicamente idéntico al ejemplo pero sin la volatilepalabra clave, y siempre parece funcionar bien.
Aroth

2
@aroth: con las JVM de hoy, puede observar que en la práctica, incluso con los ejemplos más simples, sin embargo, no puede reproducir este comportamiento de manera confiable . Con aplicaciones más complejas, a veces tiene otras acciones con garantías de visibilidad de memoria dentro de su código que hacen que funcione, lo cual es especialmente peligroso ya que no sabe por qué funciona y un cambio simple, aparentemente no relacionado en su código puede romper su aplicación ...
Holger

31

Un ejemplo común para usar volatilees usar una volatile booleanvariable 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 indicador volatile, 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 un synchronizedbloque.


27

Una variable declarada con volatilepalabra clave, tiene dos cualidades principales que la hacen especial.

  1. 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.

  2. 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

  • Todos los hilos que leen una variable volátil definitivamente leerán el último valor. Porque ningún valor almacenado en caché puede contaminarlo. Y también la solicitud de lectura se otorgará solo después de la finalización de la operación de escritura actual.

Y por otro lado,

  • Si investigamos más a fondo el n . ° 2 que he mencionado, podemos ver que la volatilepalabra 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 la volatilepalabra clave, ya está. No hay otros gastos generales sobre la seguridad del hilo.

Por el contrario,

No podemos hacer uso de la volatilepalabra clave únicamente, para satisfacer una variable compartida que tiene más de un hilo de escritor que accede a ella .


3
Esto explica la diferencia entre volátil y sincronizado.
ajay

13

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


Para hacerlo aún más claro, NO HAY NECESIDAD de establecer un volátil booleano, porque la lectura y escritura de un booleano YA ES atómica.
Kai Wang

2
@KaiWang no necesita usar volátiles en booleanos con fines de atomicidad. Pero ciertamente podría hacerlo por razones de visibilidad. ¿Es eso lo que querías decir?
SusanW

12

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.


10

En mi opinión, dos escenarios importantes además de detener el hilo en el que se usa la palabra clave volátil son:

  1. Mecanismo de bloqueo de doble control . Se usa a menudo en el patrón de diseño Singleton. En esto, el objeto singleton necesita ser declarado volátil .
  2. Despiertos espurios . El hilo a veces puede despertarse de la llamada en espera, incluso si no se ha emitido una llamada de notificación. Este comportamiento se llama despertar espurio. Esto puede contrarrestarse usando una variable condicional (bandera booleana). Ponga la llamada wait () en un ciclo while siempre que la bandera sea verdadera. Entonces, si el subproceso se despierta de la llamada de espera debido a cualquier otra razón que no sea Notify / NotifyAll, entonces encuentra que el indicador todavía es verdadero y, por lo tanto, las llamadas esperan de nuevo. Antes de llamar a notificar, configure este indicador en verdadero. En este caso, la bandera booleana se declara como volátil .

Toda la sección # 2 parece muy confusa, está combinando notificaciones perdidas, despertadores espurios y problemas de visibilidad de memoria. Además, si todos los usos de la bandera están sincronizados, entonces volátil es redundante. Creo que entiendo tu punto, pero la vigilia espuria no es el término correcto. Por favor aclarar
Nathan Hughes el

5

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'.


5

volatilesolo 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.

package io.netty.example.telnet;

import java.util.ArrayList;
import java.util.List;

public class Main {

    public static volatile  int a = 0;
    public static void main(String args[]) throws InterruptedException{

        List<Thread> list = new  ArrayList<Thread>();
        for(int i = 0 ; i<11 ;i++){
            list.add(new Pojo());
        }

        for (Thread thread : list) {
            thread.start();
        }

        Thread.sleep(20000);
        System.out.println(a);
    }
}
class Pojo extends Thread{
    int a = 10001;
    public void run() {
        while(a-->0){
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Main.a++;
            System.out.println("a = "+Main.a);
        }
    }
}

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.

    package io.netty.example.telnet;

    import java.util.ArrayList;
    import java.util.List;
    import java.util.concurrent.atomic.AtomicInteger;

    public class Main {

        public static volatile  AtomicInteger a = new AtomicInteger(0);
        public static void main(String args[]) throws InterruptedException{

            List<Thread> list = new  ArrayList<Thread>();
            for(int i = 0 ; i<11 ;i++){
                list.add(new Pojo());
            }

            for (Thread thread : list) {
                thread.start();
            }

            Thread.sleep(20000);
            System.out.println(a.get());

        }
    }
    class Pojo extends Thread{
        int a = 10001;
        public void run() {
            while(a-->0){
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Main.a.incrementAndGet();
                System.out.println("a = "+Main.a);
            }
        }
    }

4

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:

  1. Solo debe usar volátil si comprende completamente lo que hace y cómo se diferencia de sincronizado. En muchas situaciones, la volatilidad parece ser, en la superficie, una alternativa más simple y eficiente a la sincronización, cuando a menudo una mejor comprensión de la volatilidad dejaría en claro que sincronizar es la única opción que funcionaría.
  2. volátil en realidad no funciona en muchas JVM antiguas, aunque sincronizado sí. Recuerdo haber visto un documento que hacía referencia a los diversos niveles de soporte en diferentes JVM, pero desafortunadamente no puedo encontrarlo ahora. Definitivamente investigue si está utilizando Java pre 1.5 o si no tiene control sobre las JVM en las que se ejecutará su programa.

4

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.


3

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.


3

Hay dos usos diferentes de la palabra clave volátil.

  1. Impide que JVM lea valores del registro (se supone como caché) y obliga a que su valor se lea desde la memoria.
  2. Reduce el riesgo de errores de inconsistencia de memoria.

Impide que JVM lea valores en el registro y obliga a que su valor se lea desde la memoria.

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:

while (busy) {
    /* do something else */
}

El hilo de prueba continuará cuando otro hilo apague la bandera de ocupado :

busy = 0;

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.

Reduce el riesgo de errores de consistencia de memoria.

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:

  • Las lecturas y escrituras son atómicas para las variables de referencia y para la mayoría de las variables primitivas (todos los tipos, excepto los largos y los dobles).
  • Las lecturas y escrituras son atómicas para todas las variables declaradas volátiles (incluidas las variables largas y dobles).

¡Salud!


3

volatiledice 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.

ingrese la descripción de la imagen aquí

volatileLa palabra clave dice que una variable será leída y escrita directamente desde / hacia la memoria RAM . Tiene alguna huella de cálculo

Java 5extendido volatileapoyando happens-before[Acerca de]

Se produce una escritura en un campo volátil, antes de cada lectura posterior de ese campo.

volatileLa palabra clave no cura una race conditionsituación en la que varios hilos pueden escribir algunos valores simultáneamente. La respuesta es la synchronizedpalabra clave [Acerca de]

Como resultado, es seguro solo cuando un hilo escribe y otros simplemente leen el volatilevalor

volátil vs sincronizado


2

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.

thread 0 prints 0
thread 1 prints 1
thread 2 prints 2
thread 3 prints 3
thread 0 prints 0
thread 1 prints 1
thread 2 prints 2
thread 3 prints 3
thread 0 prints 0
thread 1 prints 1
thread 2 prints 2
thread 3 prints 3

Para lograr esto, podemos usar el siguiente código de ejecución completo.

public class Solution {
    static volatile int counter = 0;
    static int print = 0;
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Thread[] ths = new Thread[4];
        for (int i = 0; i < ths.length; i++) {
            ths[i] = new Thread(new MyRunnable(i, ths.length));
            ths[i].start();
        }
    }
    static class MyRunnable implements Runnable {
        final int thID;
        final int total;
        public MyRunnable(int id, int total) {
            thID = id;
            this.total = total;
        }
        @Override
        public void run() {
            // TODO Auto-generated method stub
            while (true) {
                if (thID == counter) {
                    System.out.println("thread " + thID + " prints " + print);
                    print++;
                    if (print == total)
                        print = 0;
                    counter++;
                    if (counter == total)
                        counter = 0;
                } else {
                    try {
                        Thread.sleep(30);
                    } catch (InterruptedException e) {
                        // log it
                    }
                }
            }
        }
    }
}

El siguiente enlace de github tiene un archivo Léame, que proporciona una explicación adecuada. https://github.com/sankar4git/volatile_thread_ordering


1

Desde la página de documentación de Oracle , surge la necesidad de variables volátiles para solucionar problemas de consistencia de memoria:

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 suceder antes con lecturas posteriores de esa misma variable.

Esto significa que los cambios en una volatilevariable 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 el volatile, sino también los efectos secundarios del código que provocó el cambio.

Como se explicó en la Peter Parkerrespuesta, en ausencia de un volatilemodificador, 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 actual SimpleDateFormaty 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.


1

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.


-1

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.


-1

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.


-2

A continuación se muestra un código muy simple para demostrar el requisito de volatilevariable que se utiliza para controlar la ejecución de Thread desde otro thread (este es un escenario donde volatilese requiere).

// Code to prove importance of 'volatile' when state of one thread is being mutated from another thread.
// Try running this class with and without 'volatile' for 'state' property of Task class.
public class VolatileTest {
    public static void main(String[] a) throws Exception {
        Task task = new Task();
        new Thread(task).start();

        Thread.sleep(500);
        long stoppedOn = System.nanoTime();

        task.stop(); // -----> do this to stop the thread

        System.out.println("Stopping on: " + stoppedOn);
    }
}

class Task implements Runnable {
    // Try running with and without 'volatile' here
    private volatile boolean state = true;
    private int i = 0;

    public void stop() {
        state = false;
    } 

    @Override
    public void run() {
        while(state) {
            i++;
        }
        System.out.println(i + "> Stopped on: " + System.nanoTime());
    }
}

Cuando volatileno se usa: nunca verá el mensaje ' Detenido el: xxx ' incluso después de ' Detener el: xxx ', y el programa continúa ejecutándose.

Stopping on: 1895303906650500

Cuando se volatileusa: verá el mensaje ' Detenido el: xxx ' inmediatamente.

Stopping on: 1895285647980000
324565439> Stopped on: 1895285648087300

Demostración: https://repl.it/repls/SilverAgonizingObjectcode


Al votante negativo: ¿Le gustaría explicar por qué votar negativamente? Si esto no es cierto, al menos aprenderé qué está mal. He añadido esta misma observación dos veces, pero no sé quién está eliminando una y otra vez
manikanta

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.