Parfois, l'optimisation des compilateurs et des processeurs rendra l'exécution différente de ce que nous imaginons. Pour cette raison, Java a imposé des restrictions aux compilateurs et aux processeurs. Le modèle de mémoire Java (JMM) les résume afin qu'il n'y ait pas besoin de considérer autant de détails sous-jacents lors de l'écriture de code et garantit que "tant que vous suivez les règles JMM pour écrire un programme, le résultat en cours d'exécution doit être correct."
Structure abstraite de JMM
En Java, toutes les instances et variables statiques sont stockées dans la mémoire du tas, qui peuvent être partagées entre les threads, et cette partie est également appelée variables partagées . Les variables locales, les paramètres de définition de la méthode et les paramètres de gestion des exceptions sont sur la pile et la mémoire de pile n'est pas partagée entre les threads.
Cependant, en raison de l'optimisation du compilateur et du processeur, il y aura des problèmes de visibilité avec les variables partagées. Par exemple, chez les multi-processeurs, les threads peuvent être exécutés sur différents processeurs, et le cache incohérent entre les processeurs entraînera des problèmes de visibilité avec des variables partagées . Il est possible que deux threads voient des valeurs différentes de la même variable.
JMM résume les optimisations faites par ces matériels en ce que chaque fil a une mémoire locale. Lorsque vous devez lire et écrire des variables partagées, copiez une copie de la mémoire principale à la mémoire locale. Lorsque vous écrivez des variables partagées, écrivez-les d'abord dans la mémoire locale, puis rafraîchissez-les à la mémoire principale à un moment donné à l'avenir. Lorsque la variable partagée est à nouveau lue, elle ne sera lue que depuis la mémoire locale.
De cette façon, la communication entre les threads nécessite deux étapes:
Écrivez le thread: actualisez la mémoire locale et lisez le thread: lisez la valeur mise à jour à partir de la mémoire principale
De cette façon, il y a un retard entre l'écriture et la lecture: quand la mémoire locale sera-t-elle actualisée dans la mémoire principale? Cela conduit à des problèmes de visibilité, et différents threads peuvent voir différentes variables partagées.
arrive avant
se produit littéralement avant "avant de se produire avant cela". C'est la règle que Java formule sur l'ordre de l'exécution du programme, et la synchronisation doit être suivie. De cette façon, les programmeurs n'ont qu'à rédiger le programme synchrone correct et se produit avant de garantir que les résultats en cours d'exécution ne seront pas erronés.
A se produit avant que B signifie non seulement que A est exécuté avant B, mais signifie également que le résultat d'exécution de A est visible pour B, ce qui garantit la visibilité.
A se produit avant B, A n'a pas besoin d'être exécuté avant B. Si AB alternait et que les résultats d'exécution sont toujours corrects, le compilateur et le processeur sont autorisés à optimiser la réorganisation. Donc, tant que les résultats du programme sont corrects, il n'y a aucun problème à la façon dont le compilateur et le processeur l'optimisent et les réorganisent, et tout est bon.
Les règles se déroulent avant
Règles de séquence de programme: Dans un thread, les règles de verrouillage de l'opération après l'opération précédente se déroulent avant: pour le même verrou, déverrouiller et verrouiller les règles du domaine volatil: écrivez la variable volatile et lisez l'une des variables volatiles après le fait. Transitivité de l'opération: un se produire avant B, b arrive avant c, alors un se produire avant C start () Règles: si le thread a exécute threadb.start () alors threadb.start () se produit avant toute opération join () dans le thread b: si thread a exécute threadb.join (), alors toutes les opérations dans le thread b.
L'exemple suivant aide à comprendre
double pi = 3,14; // adouble r = 1,0; // zone bdouble = pi * r * r; // c
Voici trois relations en passant avant, les règles 1 et 2 sont des règles d'ordre du programme et les règles 3 sont dérivées des règles transitives:
Un se produire avant que BB arrive avant CA se produit avant C
C dépend de A et B, mais ni A ni B ne dépendent. Ainsi, même si A et B sont réorganisés, les résultats de l'exécution ne changeront pas. Dans cette réorganisation, JMM est en cours d'exécution.
Les deux séquences d'exécution suivantes sont correctes.
Ce qui précède est tout le contenu que nous avons compilé pour l'apprentissage du modèle de mémoire Java JMM. Pour plus de questions, veuillez laisser un message ci-dessous pour discuter. Merci pour votre soutien à Wulin.com.