95 votes

Pourquoi le volatile est utilisé dans le verrouillage à double vérification

De La tête d'abord design patterns book, le modèle singleton avec un verrouillage doublement vérifié a été implémenté comme ci-dessous :

public class Singleton {
    private volatile static Singleton instance;
    private Singleton() {}
    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

Je ne comprends pas pourquoi volatile est utilisé. N'est pas volatile va à l'encontre de l'objectif de l'utilisation d'un verrouillage à double vérification, à savoir la performance ?

7 votes

Je pensais que le verrouillage à double vérification était cassé, quelqu'un l'a réparé ?

4 votes

Pour ce que ça vaut, j'ai trouvé que Head First design patterns était un livre horrible pour apprendre. En y repensant, il est parfaitement logique maintenant que j'ai appris les modèles ailleurs, mais pour apprendre sans connaître les modèles, il n'a vraiment pas servi son objectif. Mais il est très populaire, alors peut-être que c'était juste moi qui était dense :-)

0 votes

@DavidHeffernan J'ai vu cet exemple utilisé comme la seule façon de faire confiance à la jvm pour faire la DCL.

2voto

David R Tribble Points 4813

En déclarant la variable comme volatile garantit que tous les accès à celui-ci lisent effectivement sa valeur actuelle en mémoire.

Sans volatile En effet, le compilateur peut optimiser les accès à la mémoire de la variable (par exemple en conservant sa valeur dans un registre), de sorte que seule la première utilisation de la variable lit l'emplacement mémoire réel contenant la variable. Cela pose un problème si la variable est modifiée par un autre thread entre le premier et le second accès ; le premier thread ne dispose que d'une copie de la première valeur (pré-modifiée), de sorte que le second thread ne peut pas lire la variable. if teste une copie périmée de la valeur de la variable.

4 votes

-1 Je perds mes points de réputation aujourd'hui :) Le real La raison en est qu'il existe un cache mémoire, modélisé comme la mémoire locale du thread. L'ordre dans lequel la mémoire locale est transférée vers la mémoire principale n'est pas défini - c'est-à-dire, à moins que vous ne disposiez de la fonction se passe avant par exemple, en utilisant volatile . Les registres n'ont rien à voir avec les objets incomplets et le problème de la DCL.

3 votes

Votre définition de volatile est trop étroite - si c'était tout ce que volatile faisait, le verrouillage à double vérification aurait fonctionné parfaitement dans <Java5. volatile introduit une barrière mémoire rendant certains réarrangements illégaux - sans cela, même si nous ne lisons jamais de valeurs périmées de la mémoire, ce ne serait toujours pas sûr. Edit : alf m'a devancé, je n'aurais pas dû m'offrir un bon thé ;)

1 votes

@TimBender si singleton contient mutable, la purge n'a rien à voir avec une référence au singleton lui-même (enfin, il y a un lien indirect, car l'accès à un volatlie la référence à un singleton fait que votre thread relit la mémoire principale - mais c'est un effet secondaire, pas la cause d'un problème :))

1voto

irreputable Points 25577

Une lecture volatile n'est pas vraiment coûteuse en soi.

Vous pouvez concevoir un test pour appeler getInstance() dans une boucle serrée, pour observer l'impact d'une lecture volatile ; cependant, ce test n'est pas réaliste ; dans une telle situation, le programmeur appelle généralement getInstance() une fois et mettre en cache l'instance pour la durée de l'utilisation.

Une autre solution consiste à utiliser un final (voir wikipedia). Cela nécessite une lecture supplémentaire, qui peut devenir plus coûteuse que l'option volatile version. Le site final peut être plus rapide dans une boucle serrée, mais ce test est discutable, comme cela a été dit précédemment.

-1voto

js84 Points 43

Je ne suis pas sûr que le volatile va régler tous les problèmes... Voir http://www.ibm.com/developerworks/java/library/j-dcl/index.html

-2voto

1.5 Points 11

Le verrouillage doublement vérifié est une technique permettant d'éviter la création d'une autre instance de singleton lors d'un appel à la fonction getInstance est réalisée dans un environnement multithreading.

Soyez attentif

  • L'instance singleton est vérifiée deux fois avant l'initialisation.
  • La section critique synchronisée n'est utilisée qu'après avoir vérifié l'instance singleton afin d'améliorer les performances.
  • volatile sur la déclaration du membre d'instance. Cela indique au compilateur de toujours lire et écrire dans la mémoire principale et non dans le cache du CPU. Avec volatile garantissant la relation happens-before, toutes les écritures se produiront avant toute lecture de la variable d'instance.

Inconvénients

  • Puisqu'elle nécessite le volatile pour fonctionner correctement, il n'est pas compatible avec Java 1.4 et les versions inférieures. Le problème est qu'une écriture non ordonnée peut permettre à la référence d'instance d'être retournée avant que le constructeur du singleton ne soit exécuté.
  • Problème de performance à cause du déclin du cache pour les variables volatiles.
  • L'instance singleton est vérifiée deux fois avant l'initialisation.
  • C'est assez verbeux et cela rend le code difficile à lire.

Il existe plusieurs réalisations du modèle singleton, chacune ayant des avantages et des inconvénients.

  • Eager loading singleton
  • Verrouillage singleton doublement vérifié
  • Idée de support d'initialisation à la demande
  • Le singleton basé sur l'enum

La description détaillée de chacun d'entre eux est trop verbeuse, je me contente donc de mettre un lien vers un bon article Tout ce que vous voulez savoir sur Singleton

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X