Les variables précédées par le modificateur volatile afin d'obliger la machine virtuelle Java à relire la valeur des variables au sein de la mémoire partagée à chaque fois qu'elles sont accédées.

Les compilateurs Java s'autorisent à mettre en cache les variables membres dans les registres mémoires. Cette optimisation entraîne des problèmes lors d'accès concurrentiels. En effet, lorsqu'un thread modifie une copie d'un champ partagé, cette copie modifiée est mise en cache et n'est pas stockée en mémoire centrale. Si bien que si un autre thread tente d'accéder au champ en question, il ne pourra pas voir les modifications apportées à ce champ puisqu'il n'accède pas à la copie précédemment modifiée et de plus ce thread travaillera, lui aussi, sur une copie du champ d'origine. Autrement dit, les threads utilisant une variable membre partagée, n'accède qu'à des copies de cette variable dont les modifications ne peuvent être visibles pour ces threads concurrents. Une incohérence de la variable a de forte probabilité de déclencher un fonctionnement inattendu du programme.

les variables possèdant le modificateur volatile, sont chargées (load) à partir de la mémoire centrale avant chaque utilisation. Suite à leur exploitation (read ou write), les variables volatiles sont stockées (stored) en mémoire centrale. Par ce moyen, la valeur réelle d'une telle variable est assurée d'être cohérente à l'intérieur de chaque thread.

int volatile indice = 0;

D'ailleurs, les actions (chargement, stockage, lecture et écriture) sur des variables volatiles sont dites atomiques (indivisibles) de même que pour des variables de type long ou double.

Il est important de comprendre que l'utilisation du modificateur volatile nécessite de se conformer à plusieurs règles.

Si plusieurs threads sont susceptibles d'accéder à une même variable membre, et qu'un ou plusieurs threads peuvent modifier la valeur de cette variable, ainsi que tous ces threads n'utilisent pas de méthodes ou de blocs synchronisés pour lire et écrire les valeurs, alors cette variable membre doit être déclarée volatile afin de s'assurer que tous les threads puissent voir ses modifications de valeur.

Exemple [voir]
public class Volatile extends Thread {
    private volatile boolean arret = false;
    private volatile int compteur;
    private volatile int temps;

    public static void main(String args[]) throws Exception {
        Exemple thread = new Exemple();
        System.out.println("Démarrage du thread...");
        thread.start();
        thread.compteur = 0;
        thread.temps = 1000;
        Thread.sleep(thread.temps / 3);
        thread.compteur = 0;
        Thread.sleep(thread.temps);
        System.out.println("Demande d'arrêt du thread...");
        // Utilisation de arret par le thread principal Thread.currentThread()
        thread.arret = true;
        Thread.sleep(300);
        System.out.println("Fin du programme");
        System.exit(0);
    }

    public void run() {
        while (temps > 0 && !arret) {
            System.out.println("Thread en cours d'exécution : " 
                                       + compteur++ + " " + temps);
            try {
                Thread.sleep(temps / 10);
            }
            catch (InterruptedException e) {
                e.printStackTrace();
            }
            temps = temps - compteur * 10;
        }
        System.out.println("Arrêt effectif du thread");
    }
}