Guide du mot-clé volatil en Java

Guide du mot clé volatile en Java

1. Vue d'ensemble

Dans cet article rapide, nous allons nous concentrer sur un concept fondamental mais souvent mal compris du langage Java: le mot-clévolatile.

En Java, chaque thread dispose d'un espace mémoire distinct appelé mémoire de travail. ceci contient les valeurs des différentes variables utilisées pour effectuer des opérations. Après avoir effectué une opération, le thread copie la valeur mise à jour de la variable dans la mémoire principale et à partir de là, les autres threads peuvent lire la dernière valeur.

En termes simples, le mot-clévolatile marque une variable pour toujours aller dans la mémoire principale, à la fois pour les lectures et les écritures, dans le cas où plusieurs threads y accèdent.

2. Quand utiliservolatile

Dans les cas où la valeur suivante de la variable dépend de la valeur précédente, il est possible que plusieurs threads qui lisent et écrivent la variable ne se synchronisent pas, en raison d'un décalage entre la lecture et l'écriture dans la mémoire principale. .

Ceci peut être illustré par un exemple simple:

public class SharedObject {
    private volatile int count = 0;

    public void increamentCount() {
        count++;
    }
    public int getCount() {
        return count;
    }
}

With no synchronization here, a typical race condition can occur. Fondamentalement, avec un écart d'exécution entre l'incrémentation et l'écriture dans la mémoire principale, d'autres threads peuvent voir une valeur de 0 et essayer de l'écrire dans la mémoire principale.

La condition de concurrence peut bien sûr également être évitée avec l'utilisation des types de données atomiques fournis par Java commeAtomicInt ouAtomicLong.

3. Synchronisation volatile et thread

Pour toutes les applications multithread, nous devons garantir quelques règles pour un comportement cohérent:

  • Exclusion mutuelle - un seul thread exécute une section critique à la fois

  • Visibilité - les modifications apportées par un thread aux données partagées sont visibles par les autres threads afin de préserver la cohérence des données.

Les méthodes et les blocsSynchronized fournissent les deux propriétés ci-dessus, au détriment des performances de l'application.

Volatile est une primitive assez utile car ellecan help ensure the visibility aspect of the data change, without, of course, providing the mutual exclusion. Ainsi, il est utile dans les endroits où nous sommes d'accord avec plusieurs threads exécutant un bloc de code en parallèle mais nous devons nous assurer de la propriété de visibilité.

4. Garantie survenant avant

À partir de Java 5, le mot clévolatile fournit également des fonctionnalités supplémentaires qui garantissent que les valeurs de toutes les variables, y compris les variables non volatiles, sont écrites dans la mémoire principale avec l'opération d'écriture deVolatile.

Ceci s'appelle Happens-Before, car il donne une visibilité de toutes les variables à un autre thread de lecture. De plus, JVM ne réorganise pas les instructions de lecture et d’écriture des variablesvolatile.

Jetons un œil à l'exemple:

Thread 1
    object.aNonValitileVariable = 1;
    object.aVolatileVariable = 100; // volatile write

Thread 2:
    int aNonValitileVariable = object.aNonValitileVariable;
    int aVolatileVariable =  object.aVolatileVariable;

Dans ce cas, lorsqueThread 1 a écrit la valeur deaVolatileVariable alors la valeur deaNonValitileVariable est également écrite dans la mémoire principale. And even though it’s not a volatile variable, it is exhibiting a volatile behavior.

En utilisant cette sémantique, nous ne pouvons définir que quelques-unes des variables de notre classe commevolatile et optimiser la garantie de visibilité.

5. Conclusion

Dans ce didacticiel, nous avons exploré plus en détail le mot clévolatile et ses fonctionnalités, ainsi que les améliorations qui y ont été apportées à partir de Java 5.

Comme toujours, les exemples de code peuvent être trouvésover on GitHub.