Maison  >  Article  >  Java  >  Variables partagées multithread et mécanisme de collaboration en Java

Variables partagées multithread et mécanisme de collaboration en Java

WBOY
WBOYavant
2023-04-20 15:55:202034parcourir

    1. Processus et threads

    1. Le processus est la plus petite unité d'allocation de ressources pour l'exécution d'un programme

    Un processus est la plus petite unité d'allocation de ressources par le système d'exploitation, comprenant : CPU, espace mémoire, disque IO, etc. Plusieurs threads dans le même processus partagent toutes les ressources système du processus, et les processus sont directement indépendants les uns des autres. Un processus est un programme doté de certaines fonctions indépendantes qui exécute une activité en cours sur un certain ensemble de données. Un processus est une unité indépendante d'allocation et de planification des ressources dans le système.

    Un processus est une activité d'exécution d'un programme sur un ordinateur. Lorsque vous exécutez un programme, vous démarrez un processus. Évidemment, les programmes sont morts et statiques, tandis que les processus sont actifs et dynamiques. Les processus peuvent être divisés en processus système et processus utilisateur. Tous les processus utilisés pour exécuter diverses fonctions du système d'exploitation sont des processus système. Il s'agit du système d'exploitation lui-même en cours d'exécution. Les processus utilisateur sont tous des processus démarrés par vous.

    2. Le thread est la plus petite unité de planification du processeur et doit dépendre du processus pour exister.

    Le thread est une entité du processus et est l'unité de base de la planification et de la répartition du CPU. Il est plus petit que d'habitude et peut. fonctionner de manière indépendante. Le thread lui-même ne possède pas de ressources système, seulement quelques ressources essentielles à son exécution (comme un compteur de programme, un ensemble de registres et une pile), mais il peut partager toutes les ressources possédées par le processus avec d'autres threads. dans le même processus.

    3. Les threads sont partout

    Tout programme doit créer un thread, en particulier JavaQuel que soit le programme, il doit démarrer un thread principal de la fonction main Java webtâches planifiées développées, minuteries, JSP ; et Servlet, mécanisme de traitement de messages asynchrone, interface d'accès à distance RM, etc. Tout événement d'écoute, événement déclencheur onClick, etc. sont indissociables de la connaissance des threads et de la concurrence.

    2. La relation entre le nombre de cœurs de processeur et le nombre de threads

    1. Multi-core

    Multi-core : fait également référence aux multiprocesseurs monopuce (Chip Multiprocessors, appelés CMP). , CMP est développé par l'Université de Stanford aux États-Unis. L'idée est d'intégrer le SMP (processeur symétrique) dans des processeurs parallèles à grande échelle dans la même puce, et chaque processeur exécute différents processus en parallèle. Ce type de programme qui s'appuie sur plusieurs CPU exécutés en parallèle en même temps est une direction importante pour parvenir à un calcul ultra-rapide, appelé traitement parallèle.

    2. Multi-threading

    Multi-threading : Multithreading simultané en abrégé. permet à plusieurs threads sur le même processeur de s'exécuter simultanément et de partager les ressources d'exécution du processeur.

    3. Nombre de cœurs et de threads

    Nombre de cœurs et de threads : Actuellement, les CPU traditionnels sont tous multicœurs. Augmenter le nombre de cœurs revient à augmenter le nombre de threads, car le système d'exploitation effectue des tâches via des threads. De manière générale, ils ont une correspondance 1:1, ce qui signifie qu'un CPU quad-core a généralement quatre threads. Mais après que Intel a introduit la technologie hyper-threading, le nombre de cœurs et le nombre de threads ont formé une relation 1:2.

    Variables partagées multithread et mécanisme de collaboration en Java

    3. Mécanisme de rotation des tranches de temps CPU

    Lorsque nous développons habituellement, nous sentons que nous ne sommes pas limités par le nombre de cœurs CPU. Nous pouvons démarrer un thread quand nous le voulons, même sur un processeur monocœur. Pourquoi? En effet, le système d'exploitation fournit un mécanisme de rotation des tranches de temps CPU.

    La planification de la rotation des tranches de temps est l'un des algorithmes les plus anciens, les plus simples, les plus justes et les plus largement utilisés, également connu sous le nom de planification RR. Chaque processus se voit attribuer une période de temps, appelée tranche de temps, qui correspond à la durée pendant laquelle le processus s'exécute.

    4. Parallélisme et concurrence

    Par exemple, s'il y a une autoroute A à 4 voies, alors le nombre maximum de véhicules parallèles est de 4. Le nombre de véhicules marchant côte à côte sur cette autoroute en même temps est inférieur à ou égal à 4, les véhicules peuvent rouler en parallèle. CPU est également basé sur ce principe. Un CPU équivaut à une autoroute, et le nombre de cœurs ou de threads est équivalent au nombre de véhicules pouvant passer côte à côte et plusieurs CPU équivaut à plusieurs ; les autoroutes et chaque autoroute L'autoroute comporte plusieurs voies côte à côte.

    Lorsque vous parlez de concurrence, assurez-vous d'ajouter du temps unitaire, c'est-à-dire quelle est la quantité de simultanéité par unité de temps ? Il ne sert en effet à rien de sortir du temps unitaire.

    Comme le dit le proverbe, on ne peut pas faire deux choses à la fois, et c'est la même chose pour les ordinateurs. En principe, un CPU ne peut être alloué qu'à un seul processus afin d'exécuter ce processus. L'ordinateur que nous utilisons habituellement n'a qu'un seul CPU, ce qui signifie qu'il n'a qu'un seul cœur. Pour lui permettre d'effectuer plusieurs tâches et d'exécuter plusieurs processus en même temps, la technologie de concurrence doit être utilisée. La mise en œuvre de la technologie de concurrence est assez complexe, et la plus simple à comprendre est « l'algorithme de planification du processus de rotation des tranches de temps ».

    1. Concurrency

    并发: signifie que l'application peut exécuter alternativement différentes tâches. Par exemple, exécuter plusieurs threads sous un seul cœur CPU ne signifie pas exécuter plusieurs tâches en même temps. sera à une vitesse qui vous est presque imperceptible. Nous basculons constamment entre l'exécution de ces deux tâches pour obtenir l'effet « exécution simultanée », mais la vitesse d'exécution de l'ordinateur est trop rapide pour que nous puissions le remarquer.

    2. Parallèle

    Parallèle : fait référence à la capacité d'une application à effectuer différentes tâches en même temps. Par exemple : vous pouvez manger et regarder la télévision en mangeant. Ces deux choses peuvent être effectuées en même temps.

    ** La différence entre la concurrence et le parallélisme est la suivante : L'un est l'exécution alternative, l'autre est l'exécution simultanée**

    Variables partagées multithread et mécanisme de collaboration en Java

    5. Programmation concurrente élevée

    En raison de la naissance du CPU multicœur, La programmation multithread et hautement simultanée reçoit de plus en plus d'attention et d'attention.

    1. Utilisation complète des ressources CPU

    D'après l'introduction ci-dessus de CPU, on peut voir qu'il n'y a pas de noyau CPU sur le marché qui n'utilise pas le mécanisme de concurrence multithread, surtout lorsque le serveur a plus d'un CPU. L'unité de planification de base d'un programme est un thread. Un thread ne peut s'exécuter que dans un seul thread d'un cœur d'un processeur, le pire qu'il puisse faire est d'avoir la puissance de calcul de deux cœurs et de 4 threads : s'il s'agit d'un thread, cela gaspillera 3/4 des performances du processeur : si vous concevez un multi-thread, il peut fonctionner sur plusieurs threads de plusieurs cœurs de plusieurs processeurs en même temps, exploitant pleinement le processeur et réduisant le temps d'inactivité du CPU, exercer sa puissance de calcul et augmenter la concurrence.

    2. Accélérez le temps de réponse des utilisateurs

    Par exemple, la fonction de téléchargement que nous utilisons souvent, de nombreux amis ouvriront un certain abonnement, car la version d'adhésion permet de télécharger plusieurs fils de discussion, personne ne peut supporter de télécharger dans un seul fil de discussion. , pourquoi? Parce que le téléchargement multithread est rapide.

    Lorsque nous développons un programme, la vitesse de la page Web est augmentée de 1 seconde si le nombre d'utilisateurs est important, cela peut augmenter le nombre de conversions. Dans les pages Web que nous parcourons souvent, lorsque le navigateur charge la page, il ouvre quelques threads supplémentaires pour charger les ressources réseau afin d'améliorer la vitesse correspondante du site Web. Le multithreading et la haute concurrence sont omniprésents dans les ordinateurs.

    3. Rendre le code modulaire, asynchrone et simple

    Par exemple, si nous réalisons un projet de commerce électronique, passer une commande et envoyer des messages texte et des e-mails aux utilisateurs peut être divisé en deux parties : les messages texte et les e-mails. . Les étapes sont séparées en deux modules distincts et transmises à d'autres threads pour exécution. Cela augmente non seulement les opérations asynchrones, améliore les performances du système, mais rend également le programme modulaire, clair et simple.

    6. Précautions pour le multi-threading

    1. Sécurité entre les threads

    Plusieurs threads dans le même processus partagent des ressources, c'est-à-dire qu'ils peuvent tous accéder à une variable dans la même adresse mémoire.

    Par exemple : s'il n'y a que des opérations de lecture sur des variables globales et des variables statiques dans chaque thread, mais aucune opération d'écriture, d'une manière générale, cette variable globale est thread-safe si plusieurs threads effectuent des opérations d'écriture en même temps, elle est généralement nécessaire. Envisagez la synchronisation des threads, sinon la sécurité des threads pourrait être affectée.

    2. Blocage entre les threads

    Afin de résoudre le problème de sécurité entre les threads, le mécanisme de verrouillage Java est introduit. Cependant, si vous ne faites pas attention, le problème multi-thread du blocage des threads Java se produira, car différents threads. sont en attente de verrous qui ne peuvent pas être libérés du tout, ce qui fait que tous les travaux ne sont pas terminés.

    Supposons qu'il y ait deux personnes affamées, elles doivent partager un couteau et une fourchette et manger à tour de rôle, elles doivent toutes les deux obtenir deux mèches, partager le couteau et partager la fourchette. Supposons que le fil A reçoive le couteau et que le fil B reçoive la fourchette. Le fil A entrera dans l'état de blocage pour attendre la fourchette, tandis que le fil B attendra le couteau appartenant au fil A. Ceci n’est qu’un exemple artificiel, et bien qu’il soit difficile à détecter au moment de l’exécution, ce genre de situation se produit tout le temps.

    3. Trop de threads épuiseront les ressources du service et provoqueront des plantages.

    Trop de threads peuvent amener le système à créer un grand nombre de threads, ce qui consommera la mémoire système et la « commutation de transition » du processeur. système échoue, alors comment devrions-nous résoudre ce genre de problème ?

    Certaines ressources système sont limitées, comme les descriptions de fichiers. Les programmes multithread peuvent manquer de ressources car chaque thread peut vouloir une de ces ressources. Si le nombre de threads est assez important ou si le nombre de threads candidats pour une ressource dépasse de loin le nombre de ressources disponibles, il est préférable d'utiliser un pool de ressources. L’un des meilleurs exemples est le regroupement de connexions à une base de données. Chaque fois qu'un thread doit utiliser une connexion à la base de données, il en prend une dans le pool et la renvoie au pool après utilisation. Le pool de ressources est également appelé bibliothèque de ressources.

    Il y a beaucoup de choses auxquelles il faut prêter attention lors du développement d'applications multithread. J'espère que tout le monde pourra lentement comprendre ses dangers dans les travaux futurs.

    7. Notes sur le multi-threading

    Les threads coopèrent les uns avec les autres pour effectuer un certain travail. Par exemple : un thread modifie la valeur d'un objet, et un autre thread détecte le changement et effectue ensuite l'opération correspondante. avec un thread, et l'exécution finale est un autre thread. Le premier est le producteur et le second est le consommateur.Ce modèle isole « quoi » et « comment ». Un moyen simple est de laisser le thread consommateur effectuer une boucle continue pour vérifier si la variable répond aux attentes tout en définissant des conditions non satisfaites dans la boucle. . Si les conditions sont remplies, quittez la boucle while pour terminer le travail du consommateur.

    Cependant, il y a les problèmes suivants :

    • Il est difficile de garantir la ponctualité.

    • Il est difficile de réduire les dépenses. Si le temps de veille est réduit, par exemple 1 milliseconde, les consommateurs peuvent détecter les changements de conditions plus rapidement, mais cela peut consommer plus de ressources processeur, entraînant un gaspillage inutile.

    Mécanisme d'attente/notification : signifie qu'un thread A appelle la méthode wait() de l'objet O et entre dans l'état d'attente, tandis qu'un autre thread B appelle la méthode notify() ou notifyAll() de l'objet O. Thread A Après avoir reçu la notification, revenez de la méthode wait() de l'objet O pour effectuer les opérations suivantes. Les deux threads ci-dessus complètent l'interaction via l'objet O, et la relation entre wait() et notify/notifyAll() sur l'objet est comme un signal de commutation, qui est utilisé pour compléter l'interaction entre la partie en attente et la partie notifiante.

    notify() : Avertissez un thread en attente de retour de l'objet à partir de la méthode d'attente. La prémisse du retour est que le thread acquiert le verrou de l'objet et que le thread qui n'acquiert pas le verrou entre à nouveau dans l'état WAITING. .

    notifyAll() : Notifie tous les threads en attente sur l'objet

    wait() : Le thread appelant cette méthode entre dans l'état WAITING et ne reviendra que s'il attend une notification d'un autre thread ou est interrompu. notez qu'après avoir appelé la méthode wait(), le verrou de l'objet sera libéré.

    wait(long) : Délai d'attente et attente pendant un certain temps. Le paramètre time ici est en millisecondes, ce qui signifie attendre jusqu'à n millisecondes. S'il n'y a pas de notification, il expirera et reviendra.

    wait (long, int) : Pour un contrôle plus précis du délai d'attente, des nanosecondes peuvent être atteintes

    Le paradigme standard de l'attente et de la notification. La partie en attente suit les principes suivants.

    • Obtenez le verrou de l'objet.

    • Si la condition n'est pas remplie, appelez la méthode wait() de l'objet, et vérifiez toujours la condition après avoir été notifié.

    • Si les conditions sont remplies, la logique correspondante sera exécutée.

    Variables partagées multithread et mécanisme de collaboration en Java

    Le notifiant suit les principes suivants :

    • Obtenir le verrou de l'objet.

    • Modifier les conditions.

    • Notifiez tous les sujets en attente sur l'objet.

    Variables partagées multithread et mécanisme de collaboration en Java

    Avant d'appeler les méthodes des séries wait() et notify(), le thread doit obtenir le verrou au niveau de l'objet de l'objet, c'est-à-dire que la méthode wait() et notify() ne peuvent être appelées que dans une méthode synchronisée ou un bloc synchronisé. Après avoir entré la méthode wait(), le thread actuel libère le verrou. Avant de revenir de wait(), le thread est en compétition avec d'autres threads pour récupérer le verrou. () Une série de méthodes quitte le bloc de code synchronisé qui appelle notifyAll. Après cela, elles entreront en compétition. Si l'un des threads acquiert le verrou d'objet, il continuera à s'exécuter. Après avoir quitté le bloc de code synchronisé et libéré le verrou, les autres threads qui ont été réveillés continueront à rivaliser pour acquérir le verrou et continueront jusqu'à ce que tous les threads soient réveillés. avoir terminé l'exécution.

    Qui devrait utiliser notify et notifyAll ?

    Utilisez notifyAll() autant que possible, utilisez notify() avec prudence, car notify() ne réveillera qu'un seul thread et nous ne pouvons pas garantir que le thread réveillé doit être le fil dont nous avons besoin pour nous réveiller.

    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