Maison  >  Article  >  Java  >  Exemple d'analyse du modèle de mémoire volatile et multithread JMM de la programmation simultanée Java

Exemple d'analyse du modèle de mémoire volatile et multithread JMM de la programmation simultanée Java

王林
王林avant
2023-05-27 08:58:481196parcourir

1. Observez le phénomène à travers le programme

Avant de commencer à vous expliquer le modèle de cache multithread Java, examinons d'abord le morceau de code suivant. La logique de ce code est très simple : le thread principal démarre deux sous-threads, un thread 1 et un thread 2. Le thread 1 s'exécute en premier et le thread 2 s'exécute après avoir dormi pendant 2 secondes. Les deux threads utilisent une variable partagée shareFlag, avec une valeur initiale false. Si shareFlag est toujours égal à false, le thread 1 sera toujours dans une boucle infinie, nous définissons donc shareFlag sur true dans le thread 2.

public class VolatileTest {
  public static boolean shareFlag = false;
  public static void main(String[] args) throws InterruptedException {
    new Thread(() -> {
      System.out.print("开始执行线程1 =>");
      while (!shareFlag){  //shareFlag = false则一直死循环
        //System.out.println("shareFlag=" + shareFlag);
      }
      System.out.print("线程1执行完成 =>");
    }).start();
    Thread.sleep(2000);
    new Thread(() -> {
      System.out.print("开始执行线程2 =>");
      shareFlag = true;
      System.out.print("线程2执行完成 =>");
    }).start();
  }
}

Si vous n'avez pas appris le modèle de thread JMM, peut-être qu'après avoir lu le code ci-dessus, vous espérez que le résultat de sortie sera le suivant :

Démarrer l'exécution du thread 1 => Démarrer l'exécution du thread 2 => Exécution du thread 2 terminée = > Exécution du thread 1 terminée =>

Comme le montre la figure ci-dessous, les gens normaux comprennent ce code. Tout d'abord, le thread 1 est exécuté pour entrer dans la boucle, le thread 2 modifie shareFlag=true et le thread 1 sort de la boucle. Par conséquent, le thread 1 qui sort de la boucle imprimera "Exécution du thread 1 terminée =>", mais après l'expérience de l'auteur, ** "Exécution du thread 1 terminée =>" ne sera pas imprimé et le thread 1 ne sortira pas de la boucle. la boucle infinie**.

Exemple danalyse du modèle de mémoire volatile et multithread JMM de la programmation simultanée Java

2. Pourquoi ce phénomène se produit-il (modèle JMM) ?

Pour expliquer les problèmes mentionnés ci-dessus, nous devons apprendre le modèle de mémoire Java JMM (Java Memory Model). Je pense qu'il est plus précis de l'appeler modèle de mémoire multithread Java.

Exemple danalyse du modèle de mémoire volatile et multithread JMM de la programmation simultanée Java

  • Tout d'abord, dans JMM, chaque thread a sa propre mémoire de travail Lorsque le programme démarre, le thread charge (lecture et chargement) les variables partagées dans sa propre mémoire de travail, charge dans la mémoire de travail du thread Variables de mémoire. sont des copies de variables partagées dans la mémoire principale. C'est-à-dire qu'il y a trois copies de shareFlag en mémoire à ce moment-là, et leurs valeurs sont toutes égales à false.

  • Lorsque le thread 2 exécute shareFlag=true, il modifie sa copie de mémoire de travail en shareFlag=true et réécrit simultanément la valeur de la copie (store&write) dans dans la mémoire principale. shareFlag=true的时候将其工作内存副本修改为shareFlag=true,同时将副本的值同步写回(store&write)到主内存中。

  • 但是线程1的工作内存中的shareFlag=false

  • Mais le
shareFlag=false

dans la mémoire de travail du thread 1 n'a pas changé, donc le thread 1 a été dans une boucle infinie

.

3. Protocole de cohérence du cache MESI

La modification des variables partagées par le thread 2 ne sera pas perçue par le thread 1, ce qui est cohérent avec les résultats expérimentaux ci-dessus et le modèle JMM. Alors, comment le thread 1 peut-il percevoir que la valeur de la variable partagée a changé ? En fait, c'est très simple. Ajoutez simplement le mot-clé volatile à la variable partagée shareFlag.
    public volatile static boolean shareFlag = false;
  1. Le principe sous-jacent est le suivant. L'ajout du mot-clé volatile incite JMM à suivre le protocole de cohérence du cache MESI, qui contient les spécifications d'utilisation du cache suivantes (

    Si vous ne comprenez pas, vous pouvez l'ignorer. Il sera décrit dans langage simple et exemples ci-dessous. Un instant ).

  2. Modified : Indique que les données de la ligne Cache actuelle sont modifiées (Dirty), et ne sont modifiées que dans le cache du CPU actuel à ce moment, les données de la ligne Cache sont différentes des données ; dans d'autres caches, elles sont également différentes des données en mémoire pour cette ligne.

  3. Exclusif : indique que les données dans la ligne de cache actuelle sont des données valides, et qu'il n'y a pas de ligne de données de ce type dans le cache des autres processeurs et que les données de la ligne de cache actuelle sont les mêmes que les données en mémoire ; .

  4. Partagé : Cela signifie que cette ligne de données sera mise en cache dans le cache de plusieurs processeurs, et les données dans le cache sont cohérentes avec les données dans la mémoire

InvalidExemple danalyse du modèle de mémoire volatile et multithread JMM de la programmation simultanée Java : Cela signifie que les données de la ligne de cache actuelle ne sont pas valides ;

  • Les spécifications d'utilisation du cache ci-dessus peuvent être trop compliquées, pour le dire simplement,
  • Lorsque le thread 2 modifie shareFlag (voir Modifier), informez-en le. bus que j'ai modifié la variable partagée shareFlag,
  • Thread 1 surveille le Bus Lorsqu'il apprend que la variable partagée shareFlag a été modifiée, il supprimera la copie de shareFlag dans sa mémoire de travail pour la rendre invalide.
🎜🎜Lorsque le thread 1 doit utiliser à nouveau shareFlag et constate qu'il n'y a pas de copie de la variable shareFlag dans la mémoire de travail, il se rechargera (lera et chargera) à partir de la mémoire principale🎜🎜🎜

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