Maison  >  Article  >  Java  >  Explication détaillée du modèle de mémoire Java avec images et texte

Explication détaillée du modèle de mémoire Java avec images et texte

尚
avant
2019-11-30 16:27:262308parcourir

Explication détaillée du modèle de mémoire Java avec images et texte

1. Présentation

Le multitâche et la simultanéité élevée sont l'un des indicateurs importants pour mesurer la capacité de un processeur informatique. Généralement, pour mesurer les performances d'un serveur, l'indicateur Transactions par seconde (TPS) est plus illustratif. Il représente le nombre moyen de requêtes auxquelles le serveur peut répondre en une seconde, et la valeur TPS est liée aux capacités de concurrence du programme. sont très étroitement liés. Avant de discuter du modèle de mémoire et des threads Java, présentons brièvement l'efficacité et la cohérence du matériel. (Recommandé : Tutoriel vidéo Java)

2. Efficacité et cohérence du matériel

En raison du périphérique de stockage de l'ordinateur. est un écart de plusieurs ordres de grandeur entre la mémoire et la puissance de calcul du processeur, les systèmes informatiques modernes doivent donc ajouter une couche de cache (cache) avec une vitesse de lecture et d'écriture aussi proche que possible de la vitesse de calcul du processeur comme tampon entre la mémoire et le processeur. Mise en mémoire tampon : copiez les données nécessaires à l'opération dans le cache afin que l'opération puisse être effectuée rapidement. Une fois l'opération terminée, elle est synchronisée vers la mémoire à partir du cache afin que le processeur n'en ait pas besoin. attendre une lecture et une écriture lentes de la mémoire.

L'interaction de stockage basée sur le cache résout le conflit de vitesse entre le processeur et la mémoire, mais introduit un nouveau problème : la cohérence du cache. Dans un système multiprocesseur, chaque processeur possède son propre cache et partage la même mémoire principale.

Comme le montre la figure ci-dessous : les tâches informatiques de plusieurs processeurs impliquent la même mémoire principale et un protocole est nécessaire pour garantir la cohérence des données. Ces protocoles incluent MSI, MESI, MOSI et Dragon Protocol. Les opérations d'accès à la mémoire définies dans le modèle de mémoire de la machine virtuelle Java sont comparables aux opérations d'accès au cache matériel. Le modèle de mémoire Java sera présenté ultérieurement.

Explication détaillée du modèle de mémoire Java avec images et texte

De plus, afin d'utiliser pleinement l'unité de calcul à l'intérieur du processeur, le processeur peut effectuer une exécution dans le désordre du code d'entrée -Exécution de l'ordre. ) optimisation, le processeur va réorganiser les résultats du code exécuté dans le désordre après calcul pour garantir l'exactitude des résultats. Semblable à l'optimisation de l'exécution dans le désordre du processeur, le compilateur juste à temps de la machine virtuelle Java présente également une optimisation similaire de la réorganisation des instructions (Instruction Recorder).

3. Modèle de mémoire Java

Définir le modèle de mémoire Java n'est pas une tâche facile. Ce modèle doit être défini de manière assez rigoureuse. les opérations simultanées ne provoquent pas d'ambiguïté ; cependant, elles doivent également être suffisamment lâches pour que l'implémentation de la machine virtuelle dispose de suffisamment d'espace libre pour utiliser diverses fonctionnalités du matériel (registres, caches, etc.) afin d'obtenir une meilleure vitesse d'exécution. Après une longue période de vérification et de correctifs, le modèle de mémoire Java a mûri et amélioré depuis la sortie du JDK1.5.

3.1 Mémoire principale et mémoire de travail

L'objectif principal du modèle de mémoire Java est de définir les règles d'accès pour chaque variable du programme, c'est-à-dire de stocker les variables dans la mémoire de la machine virtuelle et les détails de bas niveau comme la récupération de variables de la mémoire. Les variables ici sont différentes des variables mentionnées dans la programmation Java. Elles incluent des champs d'instance, des champs statiques et des éléments qui constituent des objets tableau, mais n'incluent pas les variables locales et les paramètres de méthode. Ces derniers sont privés du thread et ne seront pas partagés. .

Le modèle de mémoire Java stipule que toutes les variables sont stockées dans la mémoire principale, et chaque thread possède sa propre mémoire de travail (qui peut être comparée au cache du processeur précédemment utilisé par). le thread est enregistré dans la mémoire principale. Toutes les opérations (lecture, affectation) des variables par le thread doivent être effectuées dans la mémoire de travail, et les variables de la mémoire principale ne peuvent pas être directement lues ou écrites.

Différents threads ne peuvent pas accéder directement aux variables dans la mémoire de travail de chacun. Le transfert des valeurs des variables entre les threads doit être effectué dans la mémoire principale. La relation interactive entre les threads, la mémoire principale et la mémoire de travail est affichée. dans la figure ci-dessous, et l'image ci-dessus est très similaire.

Explication détaillée du modèle de mémoire Java avec images et texte

La mémoire principale et la mémoire de travail ici ne sont pas le même niveau de division de la mémoire que le tas, la pile et la zone de méthode Java de la zone de mémoire Java.

3.2 Interaction inter-mémoire

À propos du protocole d'interaction spécifique entre la mémoire principale et la mémoire de travail, c'est-à-dire la manière dont une variable est copiée de la mémoire principale vers la mémoire de travail et comment le copier de la mémoire principale vers la mémoire de travail. Pour implémenter les détails de la synchronisation de la mémoire de travail vers la mémoire principale, le modèle de mémoire Java définit les huit opérations suivantes à effectuer :

1. mémoire, identifiant une variable comme un statut exclusif de Thread.

2. Déverrouiller (déverrouiller) : Agit sur la variable de mémoire principale pour libérer une variable qui est dans un état verrouillé. Seule la variable libérée peut être verrouillée par d'autres threads.

3. Lire (lire) : Agit sur la variable de la mémoire principale, en transférant une valeur de variable de la mémoire principale à la mémoire de travail du thread, afin qu'elle puisse être utilisée par l'action de chargement ultérieure

4. Charger : Agit sur les variables dans la mémoire de travail. Il place la valeur de la variable obtenue de la mémoire principale par l'opération de lecture dans une copie de la variable dans la mémoire de travail.

5. Utilisation : agit sur les variables de la mémoire de travail, en transmettant une valeur de variable dans la mémoire de travail au moteur d'exécution chaque fois que la machine virtuelle rencontre une instruction de bytecode qui doit utiliser la valeur de la variable. cette opération.

6. Attribuer (affectation) : Agit sur une variable dans la mémoire de travail. Il attribue une valeur reçue du moteur d'exécution à une variable dans la mémoire de travail chaque fois que la machine virtuelle rencontre un bytecode qui attribue une valeur. à une variable Effectuer cette opération sur commande.

7. Store (stockage) : Agit sur les variables de la mémoire de travail, transférant la valeur d'une variable de la mémoire de travail vers la mémoire principale pour les opérations d'écriture ultérieures.

8. Écrire : Agit sur les variables de la mémoire principale. Il transfère l'opération de stockage de la valeur d'une variable dans la mémoire de travail vers une variable dans la mémoire principale.

Si vous souhaitez copier une variable de la mémoire principale vers la mémoire de travail, vous devez effectuer les opérations de lecture et de chargement en séquence. Si vous souhaitez synchroniser la variable de la mémoire de travail vers la mémoire principale. , vous devez effectuer les opérations de lecture et de chargement dans l'ordre. Effectuez les opérations de stockage et d'écriture.

Le modèle de mémoire Java exige uniquement que les opérations ci-dessus soient exécutées dans l'ordre, mais rien ne garantit qu'elles doivent être exécutées en continu. Autrement dit, d'autres instructions peuvent être insérées entre la lecture et le chargement, et entre le stockage et l'écriture. Par exemple, lors de l'accès aux variables a et b dans la mémoire principale, l'ordre possible est lire a, lire b, charger b, charger a. Le modèle de mémoire Java stipule également que lors de l'exécution des huit opérations de base ci-dessus, les règles suivantes doivent être respectées :

1 L'une des opérations de lecture et de chargement, de stockage et d'écriture ne doit pas apparaître seule

.

2. Un thread n'est pas autorisé à ignorer son opération d'affectation la plus récente, c'est-à-dire que les variables doivent être synchronisées avec la mémoire principale après avoir été modifiées dans la mémoire de travail.

3. Un thread n'est pas autorisé à synchroniser les données de la mémoire de travail vers la mémoire principale sans raison (aucune opération d'attribution n'a eu lieu).

4. Une nouvelle variable ne peut être créée que dans la mémoire principale, et une variable non initialisée (charger ou attribuer) ne peut pas être utilisée directement dans la mémoire de travail. Autrement dit, avant d'effectuer des opérations d'utilisation et de stockage sur une variable, les opérations d'affectation et de chargement doivent être effectuées en premier.

5. Un seul thread est autorisé à verrouiller une variable en même temps. Le verrouillage et le déverrouillage doivent apparaître par paires

6. la valeur de cette variable dans la mémoire doit être réexécutée, charger ou affecter une opération pour initialiser la valeur de la variable avant que le moteur d'exécution n'utilise cette variable

7. Si une variable n'a pas été verrouillée par l'opération de verrouillage au préalable , il n'est pas permis d'effectuer une opération de déverrouillage ; il n'est pas non plus autorisé à déverrouiller une variable verrouillée par d'autres threads.

8. Avant d'effectuer une opération de déverrouillage sur une variable, la variable doit être synchronisée avec la mémoire principale (effectuer des opérations de stockage et d'écriture).

3.3 Réorganisation

Afin d'améliorer les performances lors de l'exécution d'un programme, les compilateurs et les processeurs réorganisent souvent les instructions. La réorganisation est divisée en trois types :

1. Réorganisation optimisée par le compilateur. Le compilateur peut réorganiser l'ordre d'exécution des instructions sans modifier la sémantique d'un programme monothread.

2. Réorganisation parallèle au niveau des instructions. Les processeurs modernes utilisent le parallélisme au niveau des instructions pour chevaucher l'exécution de plusieurs instructions. S'il n'y a pas de dépendances de données, le processeur peut modifier l'ordre dans lequel les instructions correspondent aux instructions machine.

3. Réorganisation du système de mémoire. Étant donné que le processeur utilise du cache et des tampons de lecture et d'écriture, les opérations de chargement et de stockage peuvent sembler exécutées dans le désordre.

Du code source Java à la séquence d'instructions finale réellement exécutée, les trois réordonnancements suivants seront effectués :

Explication détaillée du modèle de mémoire Java avec images et texteAfin d'assurer la visibilité de la mémoire, le compilateur Java génère la séquence d'instructions Des instructions de barrière de mémoire sont insérées le cas échéant pour désactiver certains types de réorganisation du processeur. Le modèle de mémoire Java divise les barrières de mémoire en quatre types : LoadLoad, LoadStore, StoreLoad et StoreStore :

Explication détaillée du modèle de mémoire Java avec images et textePour plus de connaissances sur Java, veuillez prêter attention à la colonne Tutoriel de base Java.

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