Maison  >  Article  >  Java  >  Comment implémenter le mécanisme d'extension de verrouillage synchronisé en Java

Comment implémenter le mécanisme d'extension de verrouillage synchronisé en Java

WBOY
WBOYavant
2023-04-28 17:13:131459parcourir

    synchronized

    Dans JDK 1.5, la synchronisation doit être implémentée en appelant le verrouillage du moniteur (Monitor). Le verrouillage du moniteur dépend essentiellement du Mutex Lock (verrouillage mutex) du système d'exploitation sous-jacent lorsque le verrouillage exclusif est activé. libéré et acquis, il doit être converti de l'état utilisateur à l'état noyau, ce qui entraîne un coût élevé et nécessite un long temps d'exécution. Nous appelons ce type de verrou qui repose sur l'implémentation de Mutex Lock du système d'exploitation. C'est un « poids lourd ». verrouillage".

    Que sont le mode utilisateur et le mode noyau ?

    Mode utilisateur : Lorsqu'un processus exécute le propre code de l'utilisateur, on dit qu'il est dans l'état d'exécution de l'utilisateur. Mode noyau : lorsqu'une tâche (processus) exécute un appel système et est piégée dans le code du noyau, nous disons que le processus est dans l'état d'exécution du noyau. À ce moment, le processeur s'exécute dans le code du noyau avec le niveau de privilège le plus élevé. .

    Comment implémenter le mécanisme dextension de verrouillage synchronisé en Java

    Pourquoi sommes-nous divisés en mode noyau et mode utilisateur ?

    En supposant qu'il n'y a pas de distinction entre le mode noyau et le mode utilisateur, le programme peut lire et écrire des ressources matérielles à volonté, comme lire, écrire et allouer de la mémoire à volonté, de cette manière, si le programmeur écrit accidentellement du contenu inapproprié dans un fichier. endroit où il ne doit pas être écrit, cela risque de provoquer un crash du système.

    Avec la distinction entre le mode utilisateur et le mode noyau, le programme effectuera une série de vérifications et d'inspections lors de l'exécution d'une opération. Ce n'est qu'après avoir confirmé qu'il n'y a pas de problème qu'il pourra exploiter les ressources normalement, afin que vous n'ayez pas à vous soucier d'une erreur accidentelle. ce faisant, c'est la situation où le système est endommagé, c'est-à-dire que la distinction entre le mode noyau et le mode utilisateur peut rendre le programme plus sûr, mais en même temps, la commutation entre les deux modes entraînera une certaine surcharge de performances.

    Extension des verrous

    Dans le JDK 1.6, afin de résoudre la consommation de performances causée par l'acquisition et la libération des verrous, les états de « verrouillage biaisé » et de « verrouillage léger » ont été introduits à ce stade, l'état synchronisé a les éléments suivants. 4 états au total Types :

    • Pas de verrouillage

    • Verrouillage biaisé

    • Verrouillage léger

    • Verrouillage lourd

    Les niveaux de verrouillage sont améliorés dans l'ordre mentionné ci-dessus. Nous allons mettre à niveau ce processus Appelez-le « extension de verrouillage ».

    Comment implémenter le mécanisme dextension de verrouillage synchronisé en Java

    PS : Jusqu'à présent, la mise à niveau des serrures est à sens unique, c'est-à-dire qu'elle ne peut être mise à niveau que de bas en haut (pas de verrouillage-> Verrouillage biaisé-> Verrouillage léger-> ; Verrouillage du niveau de poids), il n'y aura pas de dégradation du verrouillage.

    Pourquoi l'extension du verrouillage peut-elle optimiser les performances de la synchronisation ? Lorsque nous comprendrons ces états de verrouillage, nous aurons naturellement la réponse. Examinons-les ensemble.

    Verrouillage biaisé

    L'auteur de HotSpot a découvert grâce à la recherche et à la pratique que dans la plupart des cas, il n'y a pas de concurrence multithread pour les verrous, et qu'ils sont toujours acquis plusieurs fois par le même thread afin de rendre l'acquisition des threads moins chère. serrures, ils ont introduit le verrouillage Bias.

    Le verrouillage biaisé signifie qu'il favorisera le premier thread à accéder au verrou. Si un seul thread accède au verrou de synchronisation pendant le fonctionnement et qu'il n'y a pas de conflit multithread, le thread n'aura pas besoin d'être déclenché. un verrou de biais sera ajouté au fil.

    Processus d'exécution du verrou biaisé

    Lorsqu'un thread accède à un bloc de code synchronisé et acquiert un verrou, l'ID du thread biaisé par le verrouillage sera stocké dans le mot de marque de l'en-tête de l'objet. Il ne sera plus ajouté via l'opération CAS lorsque. le thread entre et sort du bloc synchronisé. Verrouillez et déverrouillez, mais détectez si le verrou de biais pointant vers le thread actuel est stocké dans Mark Word. Si l'ID du thread dans Mark Word est cohérent avec l'ID du thread consulté, vous pouvez entrer directement le. bloc de synchronisation pour l'exécution du code. Si l'ID du thread est différent, utilisez CAS pour essayer d'acquérir le verrou. Si l'acquisition réussit, entrez le bloc synchronisé pour exécuter le code. Sinon, l'état du verrou sera mis à niveau vers un verrou léger. .

    Avantages des verrous biaisés

    Les verrous biaisés sont conçus pour minimiser les commutations de verrouillage inutiles sans concurrence multithread, car l'acquisition et la libération des verrous reposent sur plusieurs instructions atomiques CAS, et les verrous biaisés uniquement. Il est nécessaire d'exécuter une instruction atomique CAS une fois lors du remplacement de l'ID de thread.

    Mark Word Extended Knowledge : Disposition de la mémoire

    Dans la machine virtuelle HotSpot, la disposition des objets stockés en mémoire peut être divisée en 3 zones suivantes :

    • En-tête d'objet (En-tête)

    • Données d'instance)

    • Remplissage aligné (Padding)

    L'en-tête de l'objet contient également :

    • Marquer le mot (champ de marque) : nos informations de verrouillage de biais sont stockées dans cette zone .

    • Klass Pointer (Pointeur d'objet de classe)

    La disposition de l'objet en mémoire est la suivante :

    Comment implémenter le mécanisme dextension de verrouillage synchronisé en Java

    Dans JDK 1.6, le verrouillage biaisé est activé par défaut. Vous pouvez désactiver le verrouillage biaisé via la commande "-XX:-UseBiasedLocking=false".

    Verrouillage léger

    Le but de l'introduction du verrouillage léger est de réduire la consommation de performances causée par le verrouillage lourd traditionnel utilisant le système d'exploitation Mutex Lock (verrouillage mutex) sans concurrence multi-thread. Si vous utilisez Mutex Lock, chaque opération d'acquisition et de libération d'un verrou entraînera une commutation entre le mode utilisateur et le mode noyau, ce qui entraînera une énorme surcharge de performances pour le système.

    Lorsque le verrouillage de biais est désactivé ou que plusieurs threads sont en compétition pour le verrouillage de biais, le verrouillage de biais sera mis à niveau vers un verrou léger. L'acquisition et la libération du verrou léger sont terminées via CAS, et l'acquisition du verrou peut se produire via un verrou léger. un certain nombre de verrous automatiques. Faites tourner pour terminer.

    Remarques

    Il faut souligner : Les verrous légers ne sont pas utilisés pour remplacer les verrous lourds Son intention initiale est de réduire la consommation de performances causée par l'utilisation de verrous lourds traditionnels sans concurrence multi-thread. Le scénario auquel les verrous légers s'adaptent est la situation dans laquelle les threads exécutent alternativement des blocs synchronisés. Si plusieurs threads accèdent en même temps, le verrou léger se transformera en un verrou lourd.

    Heavyweight Lock

    synchronized s'appuie sur le moniteur pour implémenter la synchronisation des méthodes ou la synchronisation des blocs de code. La synchronisation des blocs de code est implémentée à l'aide des instructions Monitorenter et MonitorExit. L'instruction MonitorEnter est insérée au début du bloc de code synchronisé après la compilation. Monitorexit est inséré à la fin de la méthode et de l'exception. Tout objet est associé à un moniteur. Lorsqu'un moniteur est maintenu, il sera dans un état verrouillé.

    Le code de verrouillage suivant :

    public class SynchronizedToMonitorExample {
        public static void main(String[] args) {
            int count = 0;
            synchronized (SynchronizedToMonitorExample.class) {
                for (int i = 0; i < 10; i++) {
                    count++;
                }
            }
            System.out.println(count);
        }
    }

    Après avoir compilé le code ci-dessus en bytecode, son contenu ressemble à ceci :

    Comment implémenter le mécanisme dextension de verrouillage synchronisé en Java

    Comme le montrent les résultats ci-dessus, dans la méthode principale Multiple Monitorenter et Les instructions de sortie du moniteur sont en cours d'exécution.On peut voir que la synchronisation est implémentée en s'appuyant sur le verrouillage du moniteur et que le verrouillage du moniteur repose sur le verrouillage mutex (Mutex Lock) du système d'exploitation. Le verrouillage mutex est acquis et libéré à chaque fois. le verrouillage, cela entraînera une commutation entre le mode utilisateur et le mode noyau, ce qui augmente la surcharge de performances du système.

    Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

    Déclaration:
    Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer