Modèle de mémoire JVM ---- ④

Modèle de mémoire

modèle de mémoire java

1. Atomicité, 2. Visibilité, 3. Commande, 4. CAS et classes atomiques, 5. Optimisation synchronisée

Beaucoup de gens ne peuvent pas faire la distinction entre [ structure de mémoire java ] et [modèle de mémoire java], [modèle de mémoire java] signifie Java MemoryModel (JMM).

En termes simples, JMM définit un ensemble de règles et garantit la visibilité, l'ordre et l'atomicité des données lorsque plusieurs threads lisent et écrivent des données partagées (variables membres, tableaux)

1. atomicité

1.1 Boîtier atomique
La question demande, les deux threads incrémentent la variable statique avec une valeur initiale de 0 et décrémentent l'autre de 5000 fois chacun. Le résultat est-il 0?
Insérez la description de l'image ici
1.2 Analyse des problèmes
Insérez la description de l'image ici
Le modèle de mémoire Java est le suivant: Pour terminer l'incrémentation des variables statiques, la décrémentation nécessite un échange de données dans la mémoire principale et la mémoire de thread:
Insérez la description de l'image ici
1.3 Solution


syntaxe synchronisée (mot clé synchrone)

synchronized( 对象 ) {
要作为原子操作代码
}

Insérez la description de l'image ici

Remarque: Pour un objet, un seul thread peut contenir le propriétaire à la fois, et si le propriétaire s'avère vide, un thread t1 deviendra le propriétaire et la commande Entrée moniteur est utilisée pour verrouiller le moniteur. Si t2 arrive, le propriétaire est trouvé. Quelqu'un entrera dans la EntryList, fera la file d'attente dans la zone d'attente et se bloquera. Lorsque t1 est terminé, l'instruction de sortie du moniteur informe la EntryList qu'il peut venir et gagner une capture; WaitSet se produit lorsque la méthode de notification d'attente;

2. Visibilité
Examinons d'abord un phénomène. La modification de la variable run par le thread principal n'est pas visible par le thread t, ce qui empêche le thread t de s'arrêter:

public class Demo4_2 {
    static boolean run = true;
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(()->{
            while(run){
                // ....
//                System.out.println(1);
            }
        });
        t.start();

        Thread.sleep(1000);
        run = false; // 线程t不会如预想的停下来
    }
}

Insérez la description de l'image ici
Insérez la description de l'image ici
Insérez la description de l'image ici
2.2 Solution

volatile (mot-clé variable)
Il peut être utilisé pour modifier les variables membres et les variables membres statiques. Il peut éviter que le thread recherche la valeur de la variable dans son cache de travail. Il doit obtenir sa valeur dans la mémoire principale . Le thread fonctionne sur des variables volatiles. Accès direct à la mémoire principale

2.3 Visibilité
Insérez la description de l'image ici
Notez que le bloc d'instructions synchronisé peut garantir à la fois l'atomicité du bloc de code et la visibilité des variables dans le bloc de code. Mais l'inconvénient est que la synchronisation est une opération lourde, les performances sont relativement inférieures

Si vous ajoutez System.out.println () à la boucle morte de l'exemple précédent, vous constaterez que même sans le modificateur volatile, le thread t peut voir correctement la modification de la variable d'exécution. Réfléchissez pourquoi?
Insérez la description de l'image ici
Insérez la description de l'image ici
3. Commande

3.1 Résultats étranges
Insérez la description de l'image ici
Le résultat peut également être 0
Insérez la description de l'image ici
à l'aide de l'outil de test de stress java simultané jcstress https://wiki.openjdk.java.net/display/CodeTools/jcstress

3.2 Solution
Insérez la description de l'image ici
3.3 Compréhension ordonnée
Insérez la description de l'image ici
Cette fonctionnalité est appelée "réarrangement des instructions", ** "réarrangement des instructions" sous multithread affectera l'exactitude. Par exemple, le célèbre mode de verrouillage à double vérification implémente un singleton. Les
Insérez la description de l'image ici
fonctionnalités d'implémentation ci-dessus sont:
Insérez la description de l'image ici
3.4 arrive avant
occur-before spécifie quelles opérations d'écriture sont visibles par les autres opérations de lecture de thread . Il s'agit d'un ensemble de règles de visibilité et d'ordre. Outre les règles de règles avant suivantes, JMM ne peut garantir qu'un thread écrit des variables partagées. Pour que les autres threads lisent la variable partagée, la
Insérez la description de l'image ici
Insérez la description de l'image ici
Insérez la description de l'image ici
Insérez la description de l'image ici
valeur par défaut de la variable (0, false, null) est écrite. Pour les autres threads, la variable est lue et
transitive. Si x hb-> y et y hb-> z alors Oui x hb-> z

4. CAS et atomes

4.1 CASInsérez la description de l'image ici
La couche inférieure de CAS s'appuie sur une classe non sécurisée pour appeler directement les instructions CAS de la couche inférieure du système d'exploitation. Voici un exemple d'utilisation directe d'objets non sécurisés pour la protection de la sécurité des threads.
Insérez la description de l'image ici
Insérez la description de l'image ici
Insérez la description de l'image ici
4.2 Verrouillage optimiste et verrouillage pessimiste

  • CAS est basé sur l'idée d' un verrouillage optimiste : l'estimation la plus optimiste, je n'ai pas peur que d'autres threads modifient des variables partagées, même si elle est modifiée, peu importe, je vais encore souffrir et réessayer.
  • Synchronisé est basé sur l'idée de verrouillage pessimiste: l'estimation la plus pessimiste, vous devez empêcher d'autres threads de modifier la variable partagée, vous ne voulez pas la changer quand je la verrouille, et je ne comprends le déverrouillage avant d'en avoir l'opportunité.

4.3 Opérations atomiques
Insérez la description de l'image ici
5. Optimisation synchronisée

Insérez la description de l'image ici
Lorsque l'objet est verrouillé, les informations d'en-tête d'objet seront remplacées par le bit de repère, le pointeur d'enregistrement de verrouillage de thread, le pointeur de verrouillage lourd, l'ID de thread, etc.

5.1 Serrure légère
Insérez la description de l'image ici
Le cadre de pile de chaque thread contiendra une structure d'enregistrement de verrouillage, qui peut stocker le mot de marque de l'objet verrouillé

Mark Word fait 8 octets. Lorsque l'objet est verrouillé, les informations d'en-tête d'objet sont stockées dans l'enregistrement de verrouillage du cadre de pile du thread. Une fois terminé, il est restauré et remplacé. Semblable à l'échange de cartes de visite entre Thread et Mark Word, il sera déverrouillé et remplacé à l'avenir; si l'ensemble est entré, cela signifie que le verrouillage est réussi. S'il échoue, cela signifie qu'il y a de la concurrence et doit être mis à niveau.
Insérez la description de l'image ici
5.2 Expansion du verrou
Si dans le processus d'essayer d'ajouter un verrou léger, l'opération CAS ne peut pas réussir, alors une situation est que d'autres threads ont ajouté un verrou léger (compétition) à cet objet, alors le verrou doit être étendu et la lumière sera agrandie. Le verrou de masse devient un verrou lourd.
Insérez la description de l'image ici
Insérez la description de l'image ici
5.3 Verrouillage du poids

Lorsque les verrous lourds sont en concurrence, vous pouvez également utiliser la rotation pour optimiser. Si le thread actuel tourne correctement (c'est-à-dire que le thread contenant le verrou a déjà quitté le bloc de synchronisation et libéré le verrou à ce moment), le thread actuel peut éviter le blocage.

Après Java 6, le verrou de rotation est adaptatif. Par exemple, si l'objet vient de réussir une opération de rotation, il est considéré que la probabilité de réussite de cette rotation sera élevée, donc il tournera plus de fois; sinon, il tournera moins Pas de rotation, bref, plus intelligent.

  • La rotation prendra du temps CPU, la rotation CPU monocœur est un gaspillage, la rotation CPU multicœur peut en profiter.
  • C'est comme attendre un feu rouge pour voir si la voiture est éteinte. Ne pas éteindre équivaut à tourner (le temps d'attente est plus court et rentable), éteindre équivaut à bloquer (le temps d'attente est plus long et rentable)
  • Impossible de contrôler s'il faut activer la fonction de rotation après Java 7
    Insérez la description de l'image ici
    5.4 Verrouillage du biais
    Insérez la description de l'image ici
    Insérez la description de l'image ici
    Insérez la description de l'image ici
    5.5 Autres optimisations

1. Réduisez le temps de verrouillage,
gardez le bloc de code aussi court que possible

2. Réduisez la granularité du
verrou. Divisez un verrou en plusieurs verrous pour augmenter la simultanéité, par exemple:
Insérez la description de l'image ici
2. Verrouillage grossier
Plusieurs boucles dans le bloc de synchronisation ne sont pas aussi bonnes que plusieurs boucles dans le bloc de synchronisation.
La JVM peut effectuer l'optimisation suivante, plusieurs L'opération de verrouillage de l'ajout est rugueuse à une seule fois (car le même objet est verrouillé, il n'est pas nécessaire de ressaisir plusieurs fois)

newStringBuffer().append("a").append("b").append("c");

4. Élimination des
verrous La JVM effectuera une analyse d'échappement du code. Par exemple, un objet verrouillé est une variable locale dans une méthode et ne sera pas accessible par d'autres threads. À ce stade, toutes les opérations de synchronisation seront ignorées par le compilateur Just-in-time.

5. Séparation en lecture-écriture
CopyOnWriteArrayList
ConyOnWriteSet

Référence:
https://wiki.openjdk.java.net/display/HotSpot/Synchronization
http://luojinping.com/2015/07/09/java optimisation du verrouillage /
https://www.infoq.cn/article/java -se-16-synchronisé
https://www.jianshu.com/p/9932047a89be
https://www.cnblogs.com/sheeva/p/6366782.html
https: // stackover fl ow.com/questions/46312817/does- java-ever-rebias-an-individual-lock

A publié 138 articles originaux · Comme 3 · Visiteur 7246

Je suppose que tu aimes

Origine blog.csdn.net/weixin_43719015/article/details/104887000
conseillé
Classement