Maison > Java > javaDidacticiel > le corps du texte

Introduction détaillée au principe de mise en œuvre de la haute concurrence volatile en Java

黄舟
Libérer: 2017-03-30 10:26:13
original
1428 Les gens l'ont consulté

Cet article présente principalement des informations pertinentes sur le principe d'implémentation de volatile en Java à haute concurrence. Dans la programmation simultanée multithread , synchronisé et Volatile jouent un rôle important, qui garantit la synchronisation. "visibilité" des variables partagées dans le développement multiprocesseur. Les amis qui en ont besoin peuvent se référer au

principe d'implémentation de volatile en java haute concurrence

Résumé : Synchronisé et volatile jouent un rôle important dans la programmation simultanée multithread. Volatile est un synchronisé léger, qui assure le partage de variables dans le développement multi-processeur. La visibilité signifie que lorsqu'un thread modifie une variable partagée, un autre thread peut lire la valeur modifiée. Il a moins de surcharge que la synchronisation dans certains cas

1 Définition :

javaLangage de programmationpermet aux threads d'accéder aux variables partagées, Afin de garantir que les variables partagées peuvent être mises à jour avec précision et cohérence, les threads doivent garantir que cette variable est acquise individuellement via un verrou exclusif. Le langage Java fournit du volatile, ce qui est plus pratique que les verrous dans certains cas. Si un champ est déclaré volatile, le modèle de mémoire des threads Java

garantit que tous les threads voient la même valeur de cette variable

2. Principe d'implémentation volatile

Alors, comment Volatile assure-t-il la visibilité ? Sous le processeur x86, utilisez des outils pour obtenir les instructions d'assemblage générées par le compilateur JIT pour voir ce que le CPU fera lors de l'écriture dans Volatile.

Code Java : instance = new Singleton();//l'instance est une variable volatile

Code assembleur : 0x01a3de1d : movb $0x0,0x1104800(% esi );0x01a3de24: lock addl $0x0,(%esp);

Lorsqu'une variable partagée modifiée avec une variable volatile est écrite, une deuxième ligne de code assembleur sera être ajouté. En consultant le manuel du développeur du logiciel IA-32Architecture

, nous pouvons voir que l'instruction préfixée lock provoquera deux choses sur les processeurs multicœurs.

Les données de la ligne cache

du processeur actuel seront réécrites dans la mémoire système.

Cette opération de réécriture rendra invalides les données mises en cache à cette adresse mémoire dans d'autres processeurs.

Afin d'augmenter la vitesse de traitement, le processeur ne communique pas directement avec la mémoire, mais lit d'abord les données de la mémoire système dans le cache interne (L1, L2 ou autres) avant d'effectuer l'opération. , mais il ne sait pas une fois l'opération terminée. Quand sera-t-elle écrite en mémoire ? Si une opération d'écriture est effectuée sur une variable volatile déclarée, la JVM enverra une instruction de préfixe de verrouillage au processeur pour écrire les données dans le cache. ligne où se trouve la variable dans la mémoire système. Mais même s'il est réécrit dans la mémoire, si les valeurs mises en cache par d'autres processeurs sont encore anciennes, il y aura des problèmes lors de l'exécution des opérations de calcul. Par conséquent, sous multi-processeurs, afin de garantir que les caches de chaque processeur. sont cohérents, la cohérence du cache sera atteinte, chaque processeur vérifie si sa valeur mise en cache a expiré en reniflant les données téléchargées sur le bus. Lorsque le processeur constate que l'adresse mémoire correspondant à sa ligne de cache a été modifiée, il le fera. la ligne de cache du processeur est définie sur l'état invalide Lorsque le processeur souhaite modifier ces données, il sera obligé de lire à nouveau les données de la mémoire système dans le cache du processeur.

Les instructions de verrouillage du préfixe entraîneront la réécriture du cache du processeur dans la mémoire. L'instruction de préfixe Lock provoque l'affirmation du signal LOCK# du processeur pendant l'exécution de l'instruction. Dans un environnement multiprocesseur, le signal LOCK# garantit que le processeur a l'usage exclusif de toute mémoire partagée pendant que le signal est affirmé. (Parce que cela verrouille le bus, empêchant les autres processeurs d'accéder au bus. L'impossibilité d'accéder au bus signifie que la mémoire système n'est pas accessible.) Cependant, dans les processeurs récents, le signal LOCK# ne verrouille généralement pas le bus. , mais verrouille le cache. Après tout, le verrou La surcharge du bus est relativement importante. L'impact des opérations de verrouillage sur le cache du processeur est détaillé au chapitre 8.1.4. Pour les processeurs Intel486 et Pentium, le signal LOCK# est toujours affirmé sur le bus lors des opérations de verrouillage. Mais dans les processeurs P6 et récents, si la zone mémoire en cours d'accès est déjà mise en cache dans le processeur, le signal LOCK# ne sera pas activé. Au lieu de cela, il verrouille le cache de cette zone mémoire et l'écrit dans la mémoire, et utilise le mécanisme de cohérence du cache pour garantir l'atomicité de la modification. Cette opération est appelée « verrouillage du cache ». Le mécanisme de cohérence du cache empêche les modifications simultanées. modifiées. Données de la zone mémoire mises en cache par plus de deux processeurs.

La réécriture du cache d'un processeur en mémoire invalidera le cache des autres processeurs. Le processeur IA-32 et le processeur Intel 64 utilisent le protocole de contrôle MESI (Modify, Exclusive, Shared, Invalidate) pour maintenir la cohérence entre le cache interne et les autres caches du processeur. Lorsqu'ils fonctionnent sur des systèmes à processeurs multicœurs, les processeurs IA-32 et Intel 64 peuvent détecter l'accès des autres processeurs à la mémoire système et à leurs caches internes. Ils utilisent des techniques de reniflage pour garantir que les données contenues dans son cache interne, sa mémoire système et les autres caches du processeur restent cohérentes sur le bus. Par exemple, dans les processeurs des familles Pentium et P6, si un processeur est reniflé pour détecter qu'un autre processeur a l'intention d'écrire sur une adresse mémoire qui gère actuellement l'état partagé, alors le processeur reniflant invalidera sa ligne de cache, comme suit Forcer le remplissage de la ligne de cache

à chaque accès à la même adresse mémoire

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!

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!