Cet article vous apporte des connaissances pertinentes sur java, qui organise principalement des questions connexes sur les questions d'entretien de fil, y compris la différence entre les méthodes ordinaires modifiées synchronisées et les méthodes statiques, le principe de programmation sans verrouillage CAS, volatile et synchronisé. Quelles sont les différences et ainsi de suite ? Jetons-y un coup d'œil ci-dessous. J'espère que cela sera utile à tout le monde.
Étude recommandée : "Tutoriel vidéo Java"
Les verrous d'objet sont utilisés pour les méthodes d'instance d'objet, ou une instance d'objet, et les verrous de classe sont utilisés pour les méthodes statiques d'une classe ou les objets de classe d'une classe. Nous savons qu'il peut y avoir plusieurs instances d'objet d'une classe, mais chaque classe n'a qu'un seul objet de classe, donc les verrous d'objet des différentes instances d'objet n'interfèrent pas les uns avec les autres, mais il n'y a qu'un seul verrou de classe pour chaque classe.
Une chose à noter est qu'en fait, le verrouillage de classe n'est qu'une chose conceptuelle et n'existe pas réellement. Le verrouillage de classe verrouille réellement l'objet de classe correspondant à chaque classe. Les verrous de classe et les verrous d’objet n’interfèrent pas non plus les uns avec les autres.
La visibilité signifie que lorsque plusieurs threads accèdent à la même variable, si un thread modifie la valeur de la variable, les autres threads peuvent immédiatement voir la valeur modifiée.
Puisque toutes les opérations sur les variables par les threads doivent être effectuées dans la mémoire de travail et ne peuvent pas directement lire et écrire des variables dans la mémoire principale, alors pour les variables partagées V, elles sont d'abord dans leur propre mémoire de travail puis synchronisées avec la mémoire principale. Cependant, il ne sera pas vidé dans la mémoire principale à temps, mais il y aura un certain décalage horaire. Évidemment, à ce stade, l'opération du thread A sur la variable V n'est plus visible pour le thread B.
Pour résoudre le problème de visibilité des objets partagés, on peut utiliser le mot clé volatile ou le verrou.
Les processeurs actuels supportent essentiellement l'instruction CAS(), mais les algorithmes implémentés par chaque fabricant sont différents. Chaque processus de fonctionnement CAS contient trois opérateurs : une adresse mémoire V, une valeur attendue A et une nouvelle valeur B. Pendant le fonctionnement, si le La valeur stockée à cette adresse est égale à la valeur attendue A, alors la valeur à l'adresse est affectée à la nouvelle valeur B, sinon aucune opération n'est effectuée.
L'idée de base de CAS est que si la valeur à cette adresse est égale à la valeur attendue, alors attribuez-lui une nouvelle valeur. Sinon, ne faites rien d'autre que renvoyer la valeur d'origine. Loop CAS consiste à effectuer en continu des opérations cas dans une boucle jusqu'à ce qu'elle réussisse. On peut également parler de trois problèmes majeurs avec CAS.
Un thread peut entrer à plusieurs reprises dans n'importe quel bloc de code synchronisé avec un verrou qu'il possède déjà. Synchronized et ReentrantLock sont tous deux des verrous réentrants. En termes d'implémentation, chaque fois qu'un thread acquiert un verrou, il détermine si le thread qui acquiert le verrou est lui-même et accumule simplement le compteur. Chaque fois que le verrou est libéré, le compteur est décrémenté jusqu'à ce que la calculatrice revienne à zéro, indiquant que. le fil a été complètement libéré. La couche inférieure est implémentée à l'aide d'AQS dans JUC.
Il s'agit du framework de base utilisé pour créer des verrous ou d'autres composants de synchronisation. Par exemple, ReentrantLock, ReentrantReadWriteLock et CountDownLatch sont implémentés sur la base d'AQS. Il utilise une variable membre int pour représenter l'état de synchronisation et termine le travail de mise en file d'attente des threads d'acquisition de ressources via la file d'attente FIFO intégrée. Il s'agit d'une variante d'implémentation du verrou de file d'attente CLH. Il peut réaliser 2 méthodes de synchronisation : exclusive et partagée.
La principale façon d'utiliser AQS est l'héritage. Les sous-classes héritent d'AQS et implémentent ses méthodes abstraites pour gérer l'état de synchronisation. La conception du synchroniseur est basée sur le modèle de méthode modèle, donc si nous voulons implémenter notre propre classe d'outils de synchronisation, nous en avons besoin. pour couvrir plusieurs d'entre elles, telles que tryAcquire, tryReleaseShared, etc.
Le but de cette conception est que les composants de synchronisation (tels que les verrous) sont orientés utilisateur. Elle définit l'interface permettant aux utilisateurs d'interagir avec les composants de synchronisation (par exemple, en permettant à deux threads d'accéder en parallèle), en masquant les détails d'implémentation du synchroniseur ; est pour L'implémenteur de verrous simplifie la mise en œuvre des verrous et protège les opérations sous-jacentes telles que la gestion de l'état de synchronisation, la mise en file d'attente des threads, l'attente et le réveil. Cela isole efficacement les domaines sur lesquels les utilisateurs et les responsables de la mise en œuvre doivent se concentrer.
En interne, AQS maintient un état de ressource partagé et utilise le FIFO intégré pour terminer le travail de mise en file d'attente des threads d'acquisition de ressources. La file d'attente est composée de nœuds Node un par un. Chaque nœud Node conserve une référence précédente et une référence suivante, qui pointent respectivement vers ses propres nœuds prédécesseur et successeur, formant une liste doublement liée à deux extrémités.
Principe synchronisé (ce) : implique deux instructions : Monitorenter, Monitorexit ; à en juger par les résultats de décompilation de la méthode de synchronisation, la synchronisation de la méthode n'est pas obtenue via les instructions Monitorenter et MonitorExit ; la méthode ordinaire, son Il existe un identifiant ACC_SYNCHRONIZED supplémentaire dans le pool de constantes.
La JVM implémente la synchronisation des méthodes basée sur cet identifiant : lorsque la méthode est appelée, l'instruction appelante vérifiera si l'indicateur d'accès ACC_SYNCHRONIZED de la méthode est défini. S'il est défini, le thread d'exécution obtiendra d'abord le moniteur, puis s'exécutera. une fois l'acquisition réussie. Corps de la méthode, le moniteur est libéré une fois la méthode exécutée. Lors de l'exécution de la méthode, aucun autre thread ne peut à nouveau obtenir le même objet moniteur.
Introduction de technologies telles que le verrouillage rotatif, le verrouillage rotatif adaptatif, l'élimination du verrouillage, le grossissement du verrouillage, le verrouillage biaisé, le verrouillage léger, l'analyse d'échappement et d'autres technologies pour réduire le coût des opérations de verrouillage.
Les verrous d'objet sont utilisés pour les méthodes d'instance d'objet ou une instance d'objet, et les verrous de classe sont utilisés pour les méthodes statiques d'une classe ou les objets de classe d'une classe. Nous savons qu'il peut y avoir plusieurs instances d'objet d'une classe, mais chaque classe n'a qu'un seul objet de classe, donc les verrous d'objet des différentes instances d'objet n'interfèrent pas les uns avec les autres, mais il n'y a qu'un seul verrou de classe pour chaque classe.
Une chose à noter est qu'en fait, le verrouillage de classe n'est qu'une chose conceptuelle et n'existe pas réellement. Le verrouillage de classe verrouille réellement l'objet de classe correspondant à chaque classe. Les verrous de classe et les verrous d’objet n’interfèrent pas non plus les uns avec les autres.
Il n'y a aucune garantie que le rôle de DCL soit : volatile assurera la visibilité et l'ordre des variables modifiées, garantissant qu'en mode singleton, l'ordre d'exécution lors de la création d'un objet doit être
Volatile est le mécanisme de synchronisation le plus léger. Volatile garantit la visibilité lorsque différents threads opèrent sur cette variable. Autrement dit, si un thread modifie la valeur d'une variable, la nouvelle valeur est immédiatement visible par les autres threads. Cependant, volatile ne peut pas garantir l'atomicité des opérations, donc les opérations d'écriture composites sous multi-threads entraîneront des problèmes de sécurité des threads.
Le mot-clé synchronisé peut être utilisé pour modifier des méthodes ou sous forme de blocs synchronisés. Il garantit principalement que plusieurs threads ne peuvent avoir qu'un seul thread dans une méthode ou un bloc synchronisé en même temps. Il assure la visibilité de l'accès des threads aux variables. et exclusivité, également connu sous le nom de mécanismes de verrouillage intégrés.
Le thread Daemon est un thread de support car il est principalement utilisé pour la planification en arrière-plan et le travail de support dans le programme. Cela signifie que lorsqu'il n'y a aucun thread non démon dans une machine virtuelle Java, la machine virtuelle Java se ferme. Un thread peut être défini comme thread démon en appelant Thread.setDaemon (true). Nous ne l'utilisons généralement pas. Par exemple, le thread de récupération de place est le thread Daemon.止 L'arrêt du thread : soit l'exécution de RUN est terminée, soit une anomalie non traitée provoque la fin anticipée du thread. Les API correspondant au thread Thread pour suspendre, reprendre et arrêter les opérations sont suspend(), Ensure() et stop(). Mais ces API sont obsolètes, c’est-à-dire que leur utilisation n’est pas recommandée. Parce que cela entraînera le fonctionnement du programme dans un état incertain.其他 La suspension de la sécurité est que d'autres threads interrompent l'opération d'interruption en appelant la méthode interruption () d'un thread A, et le thread interrompu doit déterminer s'il est interrompu par le thread via le thread par la méthode Thread.interrupted(. ) est utilisé pour déterminer si le thread actuel est interrompu, mais Thread.interrupted() réécrira également le bit de l'indicateur d'interruption sur false.
12. La différence entre dormir, attendre et produire. Comment le fil d'attente le réveille-t-il ?
La méthode rendement() : fait que le thread actuel abandonne la propriété du processeur, mais le moment de l'abandon ne peut pas être défini. La ressource de verrouillage ne sera pas libérée. Tous les threads exécutant rendement() peuvent être à nouveau sélectionnés par le système d'exploitation et exécutés immédiatement après être entrés dans l'état prêt.
Le fil d'attente utilise notify/notifyAll() pour se réveiller.
13. Le sommeil est-il interrompu ?
Sleep lui-même prend en charge les interruptions. Si le thread est interrompu pendant le sommeil, une exception d'interruption sera levée.
Le statut des threads en Java est divisé en 6 types :
Initial (NOUVEAU) : Un nouvel objet thread est créé, mais la méthode start() n'a pas encore été appelée. Exécuter (RUNNABLE) : dans les threads Java, les deux états prêt et en cours d'exécution sont généralement appelés « en cours d'exécution ». Une fois l'objet thread créé, d'autres threads (tels que le thread principal) appellent la méthode start() de l'objet. Le thread dans cet état est situé dans le pool de threads exécutables, en attente d'être sélectionné par la planification des threads pour obtenir le droit d'utiliser le CPU. Il est actuellement dans l'état prêt. Le thread à l'état prêt passe à l'état d'exécution (running) après avoir obtenu la tranche de temps CPU. ThreadLocal est une variable spéciale en Java. ThreadLocal fournit une copie de la variable pour chaque thread, afin que chaque thread n'accède pas au même objet à un certain moment, isolant ainsi le partage de données par plusieurs threads.
En termes d'implémentation interne, chaque thread contient un ThreadLocalMap, qui est utilisé pour enregistrer une copie des variables appartenant à chaque thread.
Durant le processus de développement, l'utilisation rationnelle des pools de threads peut apporter 3 avantages.
Premièrement : réduire la consommation de ressources.
Deuxièmement : Améliorez la vitesse de réponse.
Troisièmement : Améliorez la gestion des threads.
Il peut être implémenté en utilisant la méthode join.
Apprentissage recommandé : "Tutoriel vidéo 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!