Keywords: Volatile - Descrizione ed esempio

DOMANDA:

Cosa significa la keyword volatile in Java?


RISPOSTA:

La keyword volatile è di solito associata ad una variabile il cui valore viene salvato e ricaricato in memoria ad ogni accesso senza utilizzare i meccanismi di caching.

Spesso viene utilizzata quando differenti threads devono accedere ad una stessa variabile.

Nell'esempio di seguito, non dichiarare la variabile volatile potrebbe portare il primo Thread a non terminare mai:
package volatiletest;

public class VolatileTest {
   volatile boolean running = true; // da notare la parola chiave volatile

   public void test() {

      // lancio un primo Thread
      new Thread(new Runnable() {
        public void run() {
         int counter = 0;
         while (running)
           counter++;
         System.out.println("Thread 1 concluso. Contatore = " + counter);
        }
      }).start();

      // lancio il secondo Thread
      new Thread(new Runnable() {
        public void run() {
          try {
            Thread.sleep(100); // Questo sleep è necessario per dare al primo thead la possibilità di partire
          } catch (InterruptedException ignored) { }
          System.out.println("Thread 2 concluso");
          running = false;
        }
      }).start();
   }

   public static void main(String[] args) {
      new VolatileTest().test();
   }
}
Lanciamo l'esempio così com'è, in output avremo:
Thread 2 concluso
Thread 1 concluso. Contatore = 24047764
(il valore del contatore è ovviamente variabile)

Proviamo invece a modificare la riga 4 eliminando la parola chiave volatile, in output avremo:
Thread 2 concluso

... e il primo Thread che non termina!

Cosa è successo? Il primo Thread carica in cache il valore della variabile booleana running (impostato a true) e non va più a leggere il valore effettivo quando il secondo Thread lo modifica a false. A causa di questo valore non aggiornato il primo Thread prosegue all'infinito senza mai terminare. Dichiarando volatile la variabile running invece si costringe il Thread (o chi per esso) ad aggiornare di volta in volta il valore senza memorizzarlo in cache. Ripristinando il valore della variabile running a volatile, anche il primo Thread termina correttamente.


DETTAGLI Aggiuntivi

La domanda sorge spontanea: "ma quindi volatile equivale a synchronized per una variabile?".
La risposta è "ni", guardiamo le differenze tra synchronized e volatile in questa tabella:

Caratteristichesynchronizedvolatile
Tipo di variabileObjectObject o primitive
Consente Null?NoSi
E' bloccante?SiNo
Tutte le variabili in cache sono sincronizzate all'accesso?SiDa Java 5 in poi SI (prima no)
Quando interviene la sincronizzazione?Quando si entra o si esce nel blocco dichiarato synchronizedQuando si accede ad una variabile volatile
Si può usare in combinazione di più operazioni all'interno di operazioni atomiche?SiGet e Set atomici sono possibili solo da Java 5 in poi. Prima no.

NOTA: una variabile volatile non può essere dichiarata final

Commenti

  1. La spiegazione più chiara e semplice (in italiano) trovata sul web.Grazie!

    RispondiElimina
  2. Per chi ne avesse bisogno, ho ance un buon link per synchronized..
    http://www.html.it/faq/quando-viene-utilizzata-la-parola-riservata-synchronized/

    RispondiElimina
  3. Great post, much appreciate the time you took to write this.

    RispondiElimina

Posta un commento

Post popolari in questo blog

Arrotondamento e troncamento in Java

Eclipse: Shortcuts (scorciatoie) da tastiera

Strutture dati: List, Set, Map

Creare un eseguibile Java