[Mise à jour] --- synchronisé verrouillage de la programmation concurrente + JDK1.6 autre optimisation des mots clés synchronisé Présentation

Source Adresse: https://github.com/nieandsun/concurrent-study.git


1 JDK1.6 Vue d'ensemble de l'optimisation des mots clés synchronisé

Article précédent « [] Programmation concurrente - du point de vue des instructions de bytecode pour comprendre les principes du mot - clé synchronisé », « [] Programmation concurrente - plus de comprendre le mot - clé synchronisé dans la perspective de la principale source JVM » a été introduit dans JDK1 0,6 synchronisé mot - clé avant de la logique de traitement est 只要线程想进入bloc synchronisé 就会pour aller 调用内核函数saisir la propriété d'objet de verrouillage de surveillance associé.

Appelez la fonction du noyau passe les problèmes liés au mode noyau et le mode utilisateur, qui consomme beaucoup de ressources système, de réduire l' efficacité des processus. Et des études ont montré que dans la plupart des cas , le code est exécuté en alternance , 交替执行就不会产生并发,自然也就不会带来并发安全问题,donc ce mécanisme JDK1.6 avant le mot - clé synchronisé il y a un certain problème.

Doug Lea a fait ReentrantLock, une bonne solution à ce problème, vous pouvez regarder mon article, « [Programmation concurrente] - ReentrantLock Résolution 1 Source: Méthode de synchronisation logique de traitement en alternance exécutée . »

Il doit être parce que le mot-clé synchronisé est la raison pour JDK mot-clé originale, à droite, l'équipe de développement de la machine virtuelle HotSpot consacré à cette version de JDK1.6 beaucoup d'efforts pour parvenir à une variété de techniques d'optimisation de verrouillage, y compris verrouillage biaisé (Biased verrouillage), la lumière serrure moyens (verrouillage légère), rotation adaptatif (Spinning Adaptive), éliminant ainsi le verrouillage (suppression de verrouillage), coarsening de verrouillage (serrure coarsening), etc. - « ces technologies sont conçues pour plus efficacement partager des données entre les threads, et la résolution de problèmes la concurrence, améliorant ainsi l'efficacité du programme.


2 processus d'escalade de verrouillage synchronisé

Le processus de mise à niveau est serrure: pas de serrure -> Verrouillage biaisé -> Verrouillage léger -> poids lourd de verrouillage


2,1 verrouillage sollicité (Biased Serrure) - de même pour le cas où le fil est répété dans le bloc de code de synchronisation


2.1.1 Quel est le verrouillage biaisé

verrouillage biaisés est important d'introduire le 6 JDK, parce que HotSpot Après les auteurs de l' étude a révélé que la pratique dans 大多数情况下,Verrouillez non seulement l'absence de concurrence multi-thread, et toujours obtenir plusieurs fois par le même filPour verrouiller le fil pour obtenir un prix plus bas, l'introduction d'un verrouillage biaisé.

verrouillage sollicité de « biais » est excentré « partielle » favoritisme « partielle », cela signifie que le verrou est biaisé en faveur de la première pour obtenir son filetage, sera stocké le numéro de fil dans la serrure tête de l'objet de polarisation, après la que vous devez vérifier le fil entre et le bloc de sorties est un verrou biaisé, le drapeau de verrouillage et ThreadID peut être.

Mais il doit être retiré dès que la concurrence semblait biaisée de verrouillage de plusieurs threads, de sorte que la révocation enregistrée avant la consommation biaisée des performances de verrouillage doit être inférieure à la performance de consommation CAS opération atomique, sinon plus de mal que de bien.


2.1.2 verrouillage de verrouillage biaisé + principe Révoquer

[Lock]
Lorsque le premier fil d'acquérir le verrou et l'accès aux blocs de synchronisation, le processus de verrouillage polarisé est la suivante:

  • (1) machine virtuelle signaleront l'en-tête d'objet est réglé sur « 01 », qui est le mode biaisé.
  • (2) utiliser l'opération de CAS pour obtenir le fil de verrouillage ID est enregistré dans l'objet la marque verbale entre la CAS si l'opération est couronnée de succès, l'avenir est titulaire d'un verrou de fil de verrouillage biaisé chaque fois que vous entrez dans le bloc de synchronisation concerné, une machine virtuelle ne peut plus être une opération synchrone, haute efficacité biaisée de verrouillage.

Combiné avec Mark Word (je peux voir sur le blog « [] Programmation concurrente - la mise en page originale de l'objet java peut être prouvé si !!! ») structure de stockage peut être mieux compris:
Insérer ici l'image Description


[Révocation]
Procédé de révocation de verrouillage précontraint est la suivante:

  • (1) annuler l'opération de verrouillage sollicité doit attendre pour le point de sécurité globale (qui est déterminée par la JVM, en général, comme l'extrémité avant de la boucle, la méthode retourne sous forme de points de sécurité)
  • (2) présente un filetage de verrouillage se bloque biaisé, détermine si l'objet est verrouillé, l'état de verrouillage
  • (3) la révocation de verrouillage biaisé, pas de verrou pour récupérer (drapeau est 01) ou d'un lock léger (00 drapeaux) de l'Etat

[+ Schémas de processus de révocation de verrouillage]
serrure de verrouillage biaisés + principe de Révoquer peut être exprimé par la figure suivante:
Ceci est « l' art de la programmation Java simultanée » dans l'explication du processus de dessin, peinture tout à fait bien, ici apporté avec elle ☺☺☺.
Insérer ici l'image Description

2.1.3 polarisée vérification verrouillage

Après verrouillage biaisé en Java 6 est activé par défaut, mais uniquement activée après l'application démarre quelques secondes, vous pouvez utiliser -XX:BiasedLockingStartupDelay=0le paramètre de retard, s'il est déterminé dans un mode compétitif dans des circonstances normales toutes les applications serrures, vous pouvez XX:-UseBiasedLocking=falsefermer les paramètres de verrouillage partiales.

procédures de vérification sont les suivantes:

package com.nrsc.ch1.base.jmm.syn_study.upgrade;
import org.openjdk.jol.info.ClassLayout;
public class BiasedLockingDemo {
    
    private static class MyThread extends Thread {
        //static修饰只会初始化一次
        static Object obj = new Object();

        @Override
        public void run() {
            for (int i = 0; i < 3; i++) {
                synchronized (obj) {
                    //打印锁对象的布局
                    System.out.println(ClassLayout.parseInstance(obj).toPrintable());
                }
            }
        }
    }

    public static void main(String[] args) {
        MyThread mt = new MyThread();
        mt.start();
    }
}
  • Pour obtenir l'effet désiré, au moment de l'exécution, la nécessité d'ajouter le paramètre VM suivant '
-XX:BiasedLockingStartupDelay=0
  • Les résultats sont les suivants:

Insérer ici l'image Description

La partie verte de l'ancien 56 Marque verbale de stocker le fil ThreadId et Epoch, vous pouvez voir les valeurs 56 bits sont les mêmes que
la partie jaune de la marque verbale trois derniers 101

Ce résultat est cohérent avec le tableau décrit au point 2.1.2.


2.1.4 Avantages de verrouillage biaisé

verrouillage précontraint est d'améliorer encore les performances lorsqu'un seul fil pour effectuer bloc de synchronisation applique à un fil à plusieurs reprises obtenir le même verrou. verrouillage biaisés peut améliorer les performances avec synchronisation sans compétition.

Il est également un compromis d'avantages avec des propriétés optimisées, qui est, il est pas toujours bénéfique pour exécuter le programme, si le programme la plupart des écluses sont toujours un certain nombre de threads accès tels que pool de threads que le mode de polarisation il est redondant.

Dans verrouillage JDK5 biaisé est désactivé par défaut, mais par le verrouillage JDK6 a été biaisé activé par défaut. Mais seulement après l'application activée commence quelques secondes, vous pouvez utiliser -XX:BiasedLockingStartupDelay=0délai de fermeture des paramètres, si elle est déterminée dans un mode compétitif et tous les verrous normalement l'application, par la XX:-UseBiasedLocking=falsefermeture des paramètres de verrouillage partiales.


résumé

  • Biaisés principe de verrouillage:

Lorsque l'objet de verrouillage est le premier thread obtient, la machine virtuelle sera soumis à drapeau la tête est réglé sur « 101 », qui est le mode biaisé. En même temps, l'utilisation de l'opération CAS pour obtenir au fil de verrouillage ID est enregistré dans Mark objet Word dans la serrure, si l'opération CAS réussit, l'avenir est titulaire d'un verrou de fil de verrouillage biaisé chaque fois que vous entrez dans le bloc de synchronisation correspondant, les machines virtuelles peuvent plus aucune opération synchrone, verrouillage sollicité à haut rendement.

  • Avantages ont tendance à verrouiller

verrouillage précontraint est d'améliorer encore les performances lorsqu'un seul fil pour effectuer bloc de synchronisation applique à un fil à plusieurs reprises obtenir le même verrou. verrouillage biaisés peut améliorer les performances avec synchronisation sans compétition.


Valable pour fil dans le procédé de synchronisation alternée - 2,2 serrure léger (Serrure légère)


2.2.1 Qu'est-ce qu'un verrou léger

Léger est le nouveau mécanisme de verrouillage de verrouillage dans JDK 6 a ajouté que le nom de « léger » est par rapport à l'utilisation des termes du moniteur de verrouillage traditionnels, mécanisme de verrouillage traditionnel est appelé verrou « poids lourd ». La première chose qui doit être souligné:serrures légères ne sont pas destinés à remplacer le verrou lourd.

Le but de l'introduction de blocage léger: dans le cas de multi-fil de bloc de synchronisation effectué en alternance, afin d'éviter les performances de tête en raison de la fermeture des poids lourds, mais si plusieurs threads entrent dans la région critique dans le même temps, le verrou entraîne léger expansé mis à jour verrou lourd, donc il n'y a pas un verrou pour être léger verrou lourd alternative.


2.2.2 + léger principe de verrouillage de verrouillage révoqué

[Lock]
Lorsque la fonction de verrouillage fermé ou biaisé plusieurs threads COMPETE biaisé de verrouillage amélioré au plomb léger à verrouillage de verrouillage biaisé, il essaiera d'obtenir un verrou léger, les étapes suivantes:

  • (1) détermine si l'objet en cours a pas d'état de verrouillage (hashcode, 0, 01), et si oui, la première JVM pour établir un espace appelé les verrous (verrouillage de la fiche) dans la trame actuelle de la pile de fil pour stocker le verrou actuellement l'objet de Word copie Mark (pUT officielle cette copie plus un préfixe déplacés, à savoir déplacés Mark Word), copiez l'objet Word Mark au cadre de la pile de verrouillage enregistrement, le verrouillage Reocrd points de propriétaire à l'objet actuel.
  • (2) tentatives JVM d'utiliser la cible de l'opération CAS Word Mark mis à jour pour pointer vers le pointeur de verrouillage enregistrement, si la concurrence avec succès pour représenter la serrure, le drapeau de verrouillage devient 00, effectuer des opérations de synchronisation.
  • (3) s'il est déterminé que l'objet en cours échoue points de marque verbale à la trame de pile du thread en cours, si elle est alors le fil de courant possède déjà cet objet de verrouillage, la mise en place directe des blocs de code de synchronisation, sinon l'objet de verrouillage n'a été décrite autres threads sAISIR, puis élargi dans une serrure légère a besoin d'un verrou lourd, le drapeau de verrouillage devient 10, en attente derrière le fil passe à l'état bloqué.

[Révocation]
serrures sont propulsées par l'opération CAS est effectuée dans les étapes suivantes:

  • (1) retiré pour obtenir des données stockées dans la serrure de la Parole léger Mark déplacées.
  • (2) souscrite par l'opération CAS remplace l'objet courant de données Word Mark, en cas de succès, le verrou du succès.
  • (3) Si l'opération de remplacement CAS échoue, l'autre thread tente d'acquérir le verrou, vous devrez passer à un verrou lourd d'inflation de verrouillage léger.

[+ Schémas de processus de révocation de verrouillage]
Ici encore emprunter "l'art de Java Concurrency" dans la figure: ☺☺☺.
Insérer ici l'image Description


2.2.3 vérification de verrouillage légère

Intéressé pour essayer moi-même, vous pouvez obtenir des résultats inattendus. . .


2.2.4 avantage de verrouillage légère

Pour le verrouillage léger, sa performance est basée “对于绝大部分的锁,在整个生命周期内都是不会存在竞争的”, si la rupture est en plus de la base exclusive du coût, il y a un fonctionnement CAS supplémentaire, donc dans le cas de plusieurs threads de concurrence, léger que serrure de verrouillage poids lourds plus lent.

Dans le cas où les blocs de synchronisation sont effectués en alternance des performances de blocage des poids lourds multithread peut être évitée en raison de la consommation.


2.3 Spinlocks

Nous croyons que grâce à des articles précédents de la literie vous devriez déjà savoir, utilisez la fonction de verrouillage du moniteur appelle les fils du noyau de parc et déparcage, à savoir les discussions de parc et besoin déparcage de basculer le mode utilisateur de la CPU et le commutateur en mode noyau. parc fréquent et déparcage à la CPU comme un lourd fardeau du travail, la performance simultanée de ces systèmes d'exploitation apporteront beaucoup de pression.

En même temps, l'équipe de développement de la machine virtuelle a également noté que dans de nombreuses applications, le partage des données verrouillée 只会持续很短的一段时间, cette fois -ci de se réveiller le fil et le blocage est pas la peine. Si la machine physique a plus d'un processeur qui permet à deux ou plusieurs threads exécutent en parallèle, on peut se placer derrière cette serrure de fil de demande “稍等一下”,, mais ne donne pas le temps d'exécution du processeur, pour voir si elle est le fil qui tient le verrou va bientôt libérer le verrou. Pour faire un fil d' attente, nous pouvons 让线程执行一个死循环(自旋), cette technique est connue sous les verrous de spin. - « spin lock a été introduit dans le JDK 1.4.2, mais elle est désactivée par défaut, vous pouvez utiliser -XX: + paramètres UseSpinning pour ouvrir dans le JDK 1.6 a été modifiée en est activée par défaut.

自旋等待不能代替阻塞Et je ne parlerai pas au nombre de processeurs requis, spin-attente elle-même, bien que sans la surcharge de commutation de fil, mais il est de prendre le temps processeur, donc si le verrou est occupé pendant un court laps de temps, l'effet de la rotation attente sera très bien, au contraire, si le verrou est occupé depuis longtemps. Puis tourner le fil ne gaspillage des ressources du processeur, et ne fera aucun travail utile, mais apportera des performances inutiles. Par conséquent, le temps d'attente de rotation doit avoir une certaine limite, si la rotation est supérieure à la limite du nombre de verrouillage est toujours pas réussi, vous devez utiliser la méthode traditionnelle pour accrocher un fil. La valeur par défaut est 10 fois le nombre de tours, l'utilisateur peut utiliser les paramètres -XX: PreBlockSpin au changement.


2.4 circlips adaptatifs

Dans JDK1.6 a également introduit verrou de rotation adaptative. des moyens d' adaptation que le temps de rotation ne sont plus fixes, mais est verrouillé dans un état avec un temps de verrouillage de rotation et le propriétaire est déterminé par la précédente. Si un verrou sur la même spin-attente objet juste serrures avec succès remportés, et le verrou de maintien de fil est en cours d' exécution, la machine virtuelle pense que cela est très susceptible d'être à nouveau tour avec succès, et il permettra de spin attendre une période relativement plus de temps, par exemple 100 cycles. En outre, si un verrou pour une rotation rarement été couronnées de succès, et qu'ils voulaient entrer
lorsque le verrou sera possible d'omettre le processus de rotation, afin d'éviter le gaspillage des ressources du processeur. Avec rotation adaptative, avec le fonctionnement du programme et d' améliorer en permanence les informations de suivi des performances, la prévision de l' état de verrouillage du programme de machine virtuelle sera plus précise, la machine virtuelle deviendra de plus en plus « intelligents ».


3 autres JDK1.6 optimisation des mots clés synchronisé Présentation


3.1 élimination de verrouillage

Serrures élimination est un compilateur de temps de machine virtuelle (JIT) au moment de l' exécution, certaines exigences de code pour la synchronisation, mais ne peut être détecté partager des données verrouillées pour éliminer la concurrence. Verrouillage éliminé des principales base de jugement des 逃逸分析données pour appuyer toutes les données pour déterminer si un morceau de code, le tas ne sera pas échapper de manière à être accessible aux autres threads, il est possible de les traiter comme des données sur la pile, ils sont considérés comme privé, fermé le fil naturellement sans besoin de synchronisation. Variable est échapper, car il nécessite l'utilisation de l' analyse des données de flux machine virtuelle pour déterminer, mais le programmeur doit être très clair, comment saura qu'il n'y a aucun cas clair exigent également la synchronisation des conflits de données , il? Il y a effectivement beaucoup mesures ne sont pas programmeur synchrone ajouté, la prévalence du code synchrone dans les programmes Java peuvent dépasser l'imagination de la plupart des lecteurs.

Par exemple, suite à cette chaîne de code très simple de seulement trois sorties le résultat ajouté, que ce soit littéralement ou la sémantique de la source du programme ne sont pas synchronisées.

public class Demo01 {
    
    public static void main(String[] args) {
        contactString("aa", "bb", "cc");
    }
    public static String contactString(String s1, String s2, String s3) {
        return new StringBuffer().append(s1).append(s2).append(s3).toString();
    }
}

L'ajout StringBuffer () est une méthode synchrone, est l'existence d'un verrou (nouveau StringBuilder ()). Son champ d'application de la découverte de la machine virtuelle dynamique est confiné à l'intérieur de la méthode concatString (). C'est-à-dire citer nouvel objet StringBuilder () est jamais « échapper » à la méthode concatString (), d'autres threads ne peuvent pas y accéder, donc alors qu'il ya des verrous, mais ils peuvent être éliminés en toute sécurité, la compilation en temps après, ce code ignorera toutes les synchroniser directement exécuté.


3.2 锁 粗 de

En principe, nous sommes dans la préparation du code est toujours recommandé de limiter la portée des blocs de synchronisation aussi faible que possible, mais seulement pour la synchronisation, donc afin de rendre possible le nombre d'opérations nécessaires pour synchroniser plus petit dans la portée réelle des données partagées S'il y a conflit de verrouillage, en attendant la serrure ce fil peut obtenir le verrou le plus rapidement possible.

Dans la plupart des cas, le principe de ce qui précède sont corrects, mais si une série d'opérations successives sont répétées verrouillage et le déverrouillage d'un même objet, ou le fonctionnement de la serrure même est présent dans le corps de la boucle, et que même s'il n'y a pas de conflit de thread, fréquemment le mutex fonctionnement synchrone provoque également une perte de performances inutiles. Par exemple le code suivant:

class Demo02 {
    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer();
        //StringBuffer是同步方法,
        // 其实没必要每次append都去判断锁相关的内容,可以将整个for循环搞成同步的 ---> JVM的锁粗化可能会直接帮你这样弄
        for (int i = 0; i < 100; i++) {
            sb.append("aa");
        }
        System.out.println(sb.toString());
    }
}

Qu'est-ce que coarsening de verrouillage, je crois que vous devez comprendre, donnent défini comme suit:

JVM détecte une série de petites opérations utilisent le même objet de verrouillage, la gamme des blocs de code de synchronisation agrandie, en dehors de cette chaîne en service, de sorte que le verrouillage ne peut ajouté une fois.


fin

Publié 226 articles originaux · Praise 319 won · vues 530 000 +

Je suppose que tu aimes

Origine blog.csdn.net/nrsc272420199/article/details/105232637
conseillé
Classement