English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Parfois, l'optimisation du compilateur et du processeur peut rendre le runtime différent de ce que nous imaginons, à cette fin, Java impose certaines restrictions aux compilateurs et aux processeurs, le modèle mémoire Java (JMM) en tire des abstraction, de sorte que lors de la rédaction du code, il n'est pas nécessaire de considérer tant de détails de bas niveau, et garantit 'si le programme est rédigé en suivant les règles du JMM, son résultat de fonctionnement est toujours correct'.
structure abstraite du JMM
En Java, toutes les instances, les variables statiques sont stockées dans la mémoire heap, la mémoire heap peut être partagée entre les threads, cette partie est également appeléevariables partagées. Les variables locales, les paramètres de définition de méthode, les paramètres de traitement des exceptions sont dans la pile, la mémoire de pile n'est pas partagée entre les threads.
En raison de l'optimisation du compilateur et du processeur, cela peut entraîner des problèmes de visibilité des variables partagées, comme dans les processeurs multicœur (multi-processeur), les threads peuvent être exécutés sur des processeurs différents, etLes caches incohérents entre les processeurs peuvent entraîner des problèmes de visibilité des variables partagéesIl est possible que deux threads voient des valeurs différentes pour le même variable.
Le JMM abstrait ces optimisations matérielles en disant que chaque thread a un mémoire local. Lorsqu'il est nécessaire de lire et d'écrire des variables partagées, une copie est faite de la mémoire principale vers le mémoire local. Lorsqu'il est nécessaire d'écrire une variable partagée, elle est d'abord écrite dans le mémoire local, et elle sera mise à jour dans la mémoire principale à un moment donné à l'avenir. Lorsqu'il est nécessaire de lire à nouveau une variable partagée, il ne sera lu que dans le mémoire local.
De cette manière, la communication entre les threads nécessite deux étapes :
Thread d'écriture : mettre à jour le mémoire local dans la mémoire principale Thread de lecture : lire la valeur mise à jour de la mémoire principale
De cette manière-Il y a un décalage entre la lecture et l'écriture : quand le mémoire local est mis à jour dans la mémoire principale ? Cela entraîne des problèmes de visibilité, différentes threads peuvent voir des variables partagées différentes.
happens-avant
Sur le plan littéral, happens-before signifie 'se produire avant'. C'est une règle que Java a définie pour l'ordre d'exécution du programme, pour réaliser la synchronisation, il est nécessaire de suivre cette règle. De cette manière, le programmeur n'a besoin de rédiger que le programme de synchronisation correct, happens-before garantit que le résultat de l'exécution ne sera pas erroné.
A se produit-before B, ne signifie pas seulement que A est exécuté avant B, mais signifie également que le résultat de l'exécution de A est visible pour B, ce qui garantit la visibilité.
A se produit-before B, A n'a pas nécessairement besoin d'être exécuté avant B, si AB alternent, le résultat de l'exécution est toujours correct, le compilateur, le processeur peuvent optimiser et réordonner. Donc, tant que le résultat du programme est correct, comment le compilateur, le processeur optimisent et comment ils réordonnent n'ont pas d'importance, tout est bon.
happens-règle before
règle d'ordre du programme : dans un thread, les opérations précédentes happens-règle de verrouillage après before : déverrouiller le verrou, happens-before verrouiller règle volatile : écrire volatile variable, happens-transitivity de toute opération de lecture de cette variable volatile après before : A se produit-avant B, B se produit-avant C, A se produit-avant ThreadB.start() règle : si ThreadA exécute ThreadB.start() alors ThreadB.start() happens-avant toute opération de ThreadB join() règle : si ThreadA exécute ThreadB.join(), alors toutes les opérations happens dans ThreadB-avant ThreadB.join()
L'exemple suivant aide à comprendre happens-avant
double pi = 3.14; //A double r = 1.0; //B double area = pi * r *r; //C
Il y a trois happens ici-règle de relation before1,2est une règle d'ordre des programmes, règle3est dérivé de la règle de transitivity :
A se produit-avant B, B se produit-avant C, A se produit-avant C
C dépend de A et B, mais A et B ne dépendent pas l'un de l'autre. Donc, même si A et B sont réordonnés, le résultat d'exécution ne changera pas. Ce réordonnement, JMM est en cours d'exécution.
Les résultats des deux séquences d'exécution suivantes sont tous corrects.
Voici le contenu complet de nos réflexions sur l'apprentissage du modèle de mémoire Java JMM que nous avons organisé pour vous. Pour plus de questions, vous pouvez laisser des commentaires ci-dessous pour discuter, merci de votre soutien au tutoriel d'alarme.
Déclaration : le contenu de cet article est extrait du réseau, la propriété intellectuelle appartient à ses auteurs respectifs, le contenu est contribué et téléchargé par les utilisateurs d'Internet, ce site n'owns pas les droits de propriété, n'a pas été édité par l'homme, et n'assume pas la responsabilité des responsabilités juridiques pertinentes. Si vous trouvez du contenu suspect de violation des droits d'auteur, veuillez envoyer un e-mail à : notice#oldtoolbag.com (veuillez remplacer # par @ lors de l'envoi d'un e-mail pour signaler une violation, et fournir des preuves pertinentes. Une fois vérifié, ce site supprimera immédiatement le contenu suspect de violation de droits d'auteur.)