ProgrammationDéveloppeur Backend

Qu'est-ce qu'une variable 'volatile' en Java et comment se différencie-t-elle de 'synchronized' ? Quand et pourquoi utiliser volatile ?

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse

volatile est un modificateur de variable qui garantit la visibilité des modifications de cette variable à tous les threads. Si une variable est déclarée comme volatile, sa lecture et son écriture se font directement dans la mémoire principale, contournant les caches locaux des threads. Cela empêche la mise en cache des valeurs localement dans le thread.

synchronized est un mot-clé qui assure non seulement la visibilité, mais aussi l'exclusion mutuelle (mutual exclusion) : seul un thread peut exécuter un bloc synchronisé à un moment donné pour un objet donné.

On doit utiliser des variables volatile pour de simples drapeaux et compteurs si :

  • la valeur de la variable ne dépend pas de l'état précédent (par exemple, le compteur est écrit une seule fois et lu plusieurs fois);
  • il n'est pas nécessaire d'avoir une séquence d'opérations plus complexe (check-then-act).

Exemple d'utilisation de volatile :

class Flag { private volatile boolean running = true; public void stop() { running = false; } public void loop() { while (running) { // ... } } }

Question piégée

Peut-on utiliser volatile pour assurer l'atomiсité de l'incrémentation d'une variable ?

Réponse : Non, volatile n'assure pas l'atomiсité des opérations. Par exemple, counter++ n'est pas une opération atomique même si counter est déclaré comme volatile, car l'opération implique la lecture, la modification et l'écriture (plusieurs actions) qui peuvent être interrompues par un autre thread. L'atomiсité est assurée par synchronized ou par des classes du paquet java.util.concurrent.atomic.

Exemple :

class Counter { private volatile int count = 0; public void increment() { count++; // PAS une opération atomique ! } }

Exemples d'erreurs réelles dues à une méconnaissance des subtilités du sujet


Histoire

Dans un projet de magasin en ligne, le drapeau d'achèvement du thread de traitement des commandes a été réalisé sans volatile. En conséquence, un des threads "se coinçait" dans une boucle infinie, car il ne voyait pas le changement de variable effectué par un autre thread. Le diagnostic a pris plusieurs jours.


Histoire

Dans un système financier, un développeur a utilisé volatile int pour le compteur d'opérations. En période de forte charge, le nombre d'opérations a commencé à "disparaître". La raison est la perte d'atomicité lors d'opérations d'incrémentation complexes.


Histoire

Les développeurs ont confondu volatile et synchronized, essayant d'utiliser volatile pour garantir l'exclusion mutuelle d'accès aux sections critiques, ce qui a conduit à des data races et à des bogues difficiles à détecter dans l'application multithread.