Technopedia Center
PMB University Brochure
Faculty of Engineering and Computer Science
S1 Informatics S1 Information Systems S1 Information Technology S1 Computer Engineering S1 Electrical Engineering S1 Civil Engineering

faculty of Economics and Business
S1 Management S1 Accountancy

Faculty of Letters and Educational Sciences
S1 English literature S1 English language education S1 Mathematics education S1 Sports Education
  • Registerasi
  • Brosur UTI
  • Kip Scholarship Information
  • Performance
  1. Weltenzyklopädie
  2. Double-checked locking — Wikipédia
Double-checked locking — Wikipédia 👆 Click Here! Read More..
Un article de Wikipédia, l'encyclopédie libre.

En génie logiciel, le verrouillage à double test ou double-checked locking est un ancien patron de conception[1].

Considéré aujourd'hui comme un antipattern du fait des problèmes subtils et difficiles à déceler qu'il pose, il a été utilisé dans le passé pour réduire le surcoût d'acquisition du verrou nécessaire à l'initialisation tardive d'un singleton, en commençant par vérifier l'objet du verrou sans précaution avant, ensuite, de poser effectivement le verrou.

En Java

[modifier | modifier le code]

Prenons par exemple la classe Java suivante :

// Version mono-{{Langue|en|texte=thread}}
class Singleton1 {
    private Outil outil = null;
    public Outil getOutil() {
        if (outil == null) {
            outil = new Outil();
        }
        return outil;
    }

    // autres attributs et méthodes…
}

Le problème de cette classe est qu'elle ne fonctionne pas en environnement multi-thread. Si deux threads appellent pour la première fois getOutil() en même temps, chacun va créer l'objet en même temps que l'autre, ou l'un va obtenir une référence sur un objet partiellement initialisé. Pour éviter cela, il faut utiliser un verrou, ce qui se fait grâce à la synchronisation, comme le montre l'exemple de code ci-dessous.

// Version correcte en environnement multi-{{Langue|en|texte=thread}}, mais potentiellement coûteuse
class Singleton2 { 
    private Outil outil = null;
    public synchronized Outil getOutil() {
        if (outil == null) {
            outil = new Outil();
        }
        return outil;
    }

    // autres attributs et méthodes…
}

Ici, le premier appel à getOutil() va créer l'objet, et si d'autres threads appellent getOutil() pendant que l'objet est cours d'initialisation, ils seront mis en attente par la synchronisation jusqu'à ce que l'objet soit complètement initialisé et sa référence retournée par le premier appel du premier thread. Tous les appels suivants ne feront que retourner la référence vers l'objet précédemment initialisé.

Cependant, la synchronisation d'une méthode peut augmenter considérablement le temps de son exécution[2]. L'acquisition et la libération d'un verrou à chaque fois que la méthode est appelée pourrait donc sembler un surcoût inutile. De nombreux programmeurs ont essayé d'optimiser ce code comme suit :

  1. vérifier que la variable n'est pas encore initialisée (sans tenter d'acquérir un verrou). Si elle l'est, retourner sa valeur immédiatement ;
  2. acquérir un verrou ;
  3. re-vérifier que la variable n'est pas encore initialisée : si un autre thread a acquis le verrou juste avant, il pourrait avoir initialisé la variable entre-temps. S'il s'avère que la variable est initialisée, retourner sa valeur ;
  4. sinon, initialiser la variable et retourner sa valeur.
// Version {{Langue|en|texte=multithreaded}} erronée
// Motif "Double-Checked Locking"
class Singleton3 {
    private Outil outil = null;
    public Outil getOutil() {
        if (outil == null) {
            synchronized (this) {
                if (outil == null) {
                    outil = new Outil();
                }
            }
        }
        return outil;
    }

    // autres attributs et méthodes…
}

Intuitivement, cet algorithme semble une solution efficace au problème posé. Cependant, il soulève des problèmes subtils et difficiles à tracer. Ainsi, considérons la séquence d'événements suivante :

  1. le thread A remarque que la variable partagée n'est pas initialisée. Il acquiert donc le verrou et commence à initialiser la variable ;
  2. du fait de la sémantique du langage de programmation, le code généré par le compilateur a le droit de modifier la variable partagée avant que A ait terminé l'initialisation, de sorte que la variable référence un objet partiellement initialisé (par exemple parce que le thread commence par allouer la mémoire, puis place la référence vers le bloc mémoire alloué dans la variable, avant, enfin, d'appeler le constructeur qui va initialiser le bloc mémoire) ;
  3. le thread B remarque que la variable partagée a été initialisée (ou, tout au moins, semble l'être), et retourne sa valeur immédiatement sans tenter d'acquérir un verrou. Si, ensuite, la variable partagée est utilisée avant que A n'ait eu le temps de terminer son initialisation, le programme risque fort de planter.

L'un des dangers du double-checked locking est que, souvent, cela semblera fonctionner. Cela dépend du compilateur, de la manière dont les threads sont ordonnancés par le système d'exploitation, et aussi d'autres mécanismes de gestion de la concurrence d'accès aux données. Reproduire les cas de plantage peut s'avérer d'autant plus difficile qu'ils sont hautement improbables lorsque le code est exécuté au sein d'un débogueur. L'utilisation du double-checked locking doit donc être bannie autant que possible.

Néanmoins, JavaSE 5.0 propose une solution à ce problème avec le mot réservé volatile qui garantit que des threads différents gèrent correctement l'accès concurrent à l'instance unique du singleton[3] :

// Fonctionne grâce à la nouvelle sémantique du mot-clé volatile
// Ne fonctionne pas avec Java 1.4 ou précédent
class Singleton4 {
    private volatile Outil outil = null;
    public Outil getOutil() {
        if (outil == null) {
            synchronized (this) {
                if (outil == null) {
                    outil = new Outil();
                }
            }
        }
        return outil;
    }

    // autres attributs et méthodes…
}

Cependant, cette sécurité d'accès a un prix : l'accès à une variable volatile est moins efficace que l'accès à une variable normale.

De nombreuses versions du patron double-checked locking qui n'utilisent pas de synchronisation explicite ou de variable volatile ont été proposées. À part celles qui reposent sur le mot-clé enum ou le motif de support d'initialisation à la demande, toutes se sont révélées incorrectes[4],[5].

Avec Microsoft Visual C++

[modifier | modifier le code]

On peut implémenter le double-checked locking avec Visual C++ 2005 si le pointeur vers la ressource est déclaré volatile. Visual C++ 2005 garantit que les variables volatiles se comportent comme des barrières, comme avec JavaSE 5.0, empêchant aussi bien le compilateur que le processeur de réordonnancer les lectures et écritures à ces variables pour les rendre plus efficaces.

Les versions précédentes de Visual C++ n'offraient pas cette garantie. Cependant, marquer le pointeur vers la ressource comme volatile pénalise les performances d'une manière ou d'une autre, en particulier si le pointeur est visible ailleurs dans le code : le compilateur le traitera comme une barrière partout où il est utilisé, même lorsque cela n'est pas nécessaire.

Références

[modifier | modifier le code]
  1. ↑ Schmidt, D et al., Pattern-Oriented Software Architecture, vol. 2, 2000, p. 353-363
  2. ↑ Boehm, Hans-J., Threads Cannot Be Implemented As a Library, ACM 2005, p. 265
  3. ↑ La nouvelle sémantique du mot clé volatile est décrite dans [1].
  4. ↑ [2]
  5. ↑ [3]

Voir aussi

[modifier | modifier le code]

Articles connexes

[modifier | modifier le code]
  • Support d'initialisation à la demande en Java.
  • Antipatterns

Liens externes

[modifier | modifier le code]
  • (en) Implémentation de divers motifs Singleton, y compris le Double Checked Locking Mechanism sur TEKPOOL
  • (en) Description du Double Checked Locking sur le référentiel de motifs de Portland
  • (en) Description du Double Checked Locking brisé sur le référentiel de motifs de Portland
  • (en) Scott Meyers et Andrei Alexandrescu, article C++ and the Perils of Double-Checked Locking (475 Ko)
  • (en) Brian Goetz, article Double-checked locking: Clever, but broken
  • (en) David Bacon et al., The Double-Checked Locking is Broken Declaration
  • (en) Double-checked locking et le motif Singleton
  • (en) Mot-clé volatile dans VC++ 2005


v · m
Patrons de conception
Création
  • Fabrique abstraite
  • Monteur
  • Fabrique
  • Prototype
  • Singleton
Structure
  • Adaptateur
  • Pont
  • Composite
  • Décorateur
  • Façade
  • Poids-mouche
  • Proxy
Comportement
  • Chaîne de responsabilité
  • Commande
  • Interpréteur
  • Itérateur
  • Médiateur
  • Mémento
  • Observateur
  • État
  • Stratégie
  • Patron de méthode
  • Visiteur
Fonctionnel
  • Fermeture
  • Curryfication
  • Composition de fonctions
  • Foncteur
  • Monade
  • Générateur
Patron d'architecture
  • ADR (en)
  • Active record
  • Broker (en)
  • Client-serveur
  • DAO
  • Data mapper
  • DTO
  • DDD
  • ECB
  • ECS (en)
  • EDA
  • Front controller (en)
  • Identity map (en)
  • Interceptor (en)
  • Implicit invocation (en)
  • Inversion de contrôle
  • Model 2 (en)
  • MOM
  • Microservices
  • MVA (en)
  • MVC
  • MVP
  • MVVM
  • Application monolithe
  • Architecture en couches
    • trois tiers
  • Naked objects (en)
  • Pair-à-pair
  • Publish-subscribe
  • PAC
  • POC
  • REST
  • SOA
  • Service locator (en)
  • SN (en)
  • SBA (en)
  • Specification (en)
Autres patrons
  • Modèle de Seeheim
  • Mémoïsation
  • Post-redirect-get
  • Support d'initialisation à la demande
  • Signaux et slots
  • Désignation chaînée
  • Double-checked locking
  • MapReduce
  • Reactor
  • Fonction de rappel
  • icône décorative Portail de la programmation informatique
Ce document provient de « https://fr.teknopedia.teknokrat.ac.id/w/index.php?title=Double-checked_locking&oldid=211204474 ».
Catégorie :
  • Patron de conception
Catégories cachées :
  • Article contenant un appel à traduction en anglais
  • Portail:Programmation informatique/Articles liés
  • Portail:Informatique/Articles liés

  • indonesia
  • Polski
  • الرية
  • Deutsch
  • English
  • Español
  • Français
  • Italiano
  • مصر
  • Nederlands
  • 本語
  • Português
  • Sinugboanong Binisaya
  • Svenska
  • Українска
  • Tiếng Việt
  • Winaray
  • 中文
  • Русски
Sunting pranala
Pusat Layanan

UNIVERSITAS TEKNOKRAT INDONESIA | ASEAN's Best Private University
Jl. ZA. Pagar Alam No.9 -11, Labuhan Ratu, Kec. Kedaton, Kota Bandar Lampung, Lampung 35132
Phone: (0721) 702022
Email: pmb@teknokrat.ac.id