La position actuelle:Accueil du site>Explication détaillée du principe de co - intégration en go

Explication détaillée du principe de co - intégration en go

2022-07-23 18:10:15Bonjour tout le monde. Je suis un bon camarade de classe.


Pourquoi avoir un programme de coopération?

Nous utilisons des usines pour représenter les ordinateurs,Et l'espace mémoire est l'équivalent du terrain de l'usine,On peut donc penser que le processus est l'usine dans l'usine,Il occupe le terrain de l'usine.(L'Unit é minimale de ressources allouées au processus)
Insérer la description de l'image ici

Qu'est - ce qu'un thread?Nous continuons à utiliser ce scénario pour comprendre,Le fil est maintenant équivalent à une ligne de travail courante dans l'usine(L'Unit é minimale de programmation des ressources au fil du temps),Il peut y avoir plusieurs pipelines par bâtiment(Un processus peut avoir plusieurs fils),La présence d'un pipeline occupe l'espace de la centrale(Le thread utilise la mémoire allouée au processus par le système,Et la mémoire partagée entre les mêmes Threads).

Insérer la description de l'image ici

Nous avons lancé deux fragments de code pour simuler l'état de fonctionnement simultané des fils,Comme le montre la figure ci - dessous:JeanCPUBasculer entre plusieurs fils,Comme le montre la figure ci - dessous,CPUExécutez d'abord le thread 1,Obtenir des résultats intermédiaires,Et puis le système a faitCPUBasculer;

![Insérer la description de l'image ici](https://img-blog.csdnimg.cn/821e17a859fc446ca0f5643dbc549824.pn
Passer au thread 2 plus tard ,Comme le montre la figure ci - dessous, Obtenir des résultats intermédiaires pour thread II ,En boucle, Un tel mononoyau CPU Cela permet un travail simultané multithreadé .

Insérer la description de l'image ici
Par le processus ci - dessus , Nous pouvons savoir que le fil prendra CPUTemps, Et l'ordonnancement des fils doit être effectué par le système ,Ça va coûter cher., Si vous utilisez toujours le scénario ci - dessus pour comprendre , Le fil correspond à la ligne de production de l'usine ( Le programme qui tourne dans le fil est le processus de production ), Les heures de travail des travailleurs seront occupées . Les inconvénients du thread sont les suivants :

  • Le thread lui - même prend beaucoup de ressources
  • Les frais généraux de fonctionnement du thread sont élevés
  • Frais généraux de commutation de fil

Comment fonctionne le co - programme ? La première étape consiste à exécuter le Code et l'état de l'exécution temporaire ( Comme la valeur médiane de la variable ),En ce momentCPU Sera fixé à un fil pour l'exécution , Donc il n'y a pas de frais généraux de commutation pour le thread , En plaçant les données relatives au co - thread sur le thread ,JeanCPUPour mettre en œuvre, Stocker les résultats intermédiaires dans l'accord après l'exécution ,Et vider, Passez à l'accord II .

Insérer la description de l'image ici

L'exécution de la co - procédure 2 est similaire à celle de la co - procédure 1 , Il est également exécuté en le plaçant d'abord sur le fil , Puis sauvegardez les variables intermédiaires pertinentes .

Insérer la description de l'image ici

De cette façon, le même thread exécute plusieurs co - threads . L'essence de la collaboration est d'emballer l'état de fonctionnement d'une section de données , Peut être programmé entre les fils , Donc le co - thread ne remplace pas le thread , Le co - thread fonctionne également sur le thread (Un thread est une ressource pour un co - thread, Le co - thread utilise cette ressource pour exécuter ).Un tel avantage, C'est - à - dire les avantages de l'Association :

  • Utilisation des ressources: Le co - thread peut utiliser n'importe quel thread pour exécuter ,Pas besoin d'attendreCPURépartition;
  • Programmation rapide: Les co - programmes peuvent être programmés rapidement ( Évitez les appels système et les commutateurs ),Changement rapide;
  • Concurrence en hauteur: Un nombre limité de Threads peut concurrencer beaucoup de co - threads ;

La nature de la co - procédure

Vous pouvez d'abord utilisergo Nom de la fonction()Pour lancer un programme de collaboration.IngoDans la langue, L'essence du processus de coordination est un processus appelé gStructure de, En raison du grand nombre de membres à l'intérieur de la structure , Nous prenons quelques variables importantes pour illustrer ,Les détails sont les suivants:

Insérer la description de l'image ici

D'abord, à gauche, la structure de la coproduction , Cet article se concentre principalement sur 4Variables structurelles, La première variable est stackStructure, Il y a deux pointeurs dans la structure , Pointeurs de haut niveau pour les données dans la pile avant de pointer séparément hi Et le pointeur bas lo;

La deuxième variable estschedStructure,L'un d'euxgobufStructure,gobuf L'état actuel de fonctionnement du programme est stocké dans ,Par exemple:sp C'est le pointeur de pile , Une donnée pointant vers la pile de pression , En fait, c'est une fonction en cours d'exécution , À l'exception de la première pc C'est le compteur de programme , Où est stocké la ligne de code actuellement en cours d'exécution .

Troisième variableatomicstatus, Ce qui est stocké, c'est l'état du programme de coopération ;Quatrième variablegoid, C'est un changement de co - programme id.

Comment le co - thread s'exécute dans le thread

Nous savons que le co - travail est effectué avec des fils , Alors regardons le bas du fil , Comprendre l'Association des Threads et des co - threads ,Ingo Le fil central est essentiellement un mStructure de, Nous nous concentrons également sur quelques - unes des variables pertinentes .
Insérer la description de l'image ici

VariablesSens
g0g0Co - Process, Fonctionnement du régulateur
curg Le programme est actuellement en cours d'exécution
mOS Mis en œuvre séparément pour un système d'exploitation particulier , Est l'information de thread du système d'exploitation

Ingo Chaque thread exécute une série de tâches en boucle , Aussi connu sous le nom de boucle à fil unique, il est montré dans la figure suivante : Pile à gauche , L'ordre des fonctions exécutées par le thread bit droit , L'approche opérationnelle est l'approche collaborative .

Insérer la description de l'image ici
La pile de collaboration générale ne peut enregistrer que les informations commerciales de la méthode d'affaires , Et il n'y a pas de pile normale de co - threads avant que le thread n'ait pas de co - threads . Donc en mémoire, il y a un g0Pile, Informations spécialement conçues pour enregistrer les sauts d'appels de fonctions . Le tableau suivant montre l'environnement d'exécution

Nom de la fonctionContenu du travail
schedule() Obtenir un programme de collaboration qui peut être exécuté , Et appeler avec le co - programme obtenu comme paramètre execute
execute() Initialiser les structures associées pour cette collaboration ,Parsched La structure appelle pour le paramètre gogo
gogo() Assembler les méthodes de mise en oeuvre ,AccèsgobufStructure, Appuyez sur la pile de co - parcours normale goexitFonctions, Obtient le nombre de lignes de code enregistrées dans le compteur de programme actuel , Et faire un saut pour exécuter la méthode d'affaires
Méthodes de fonctionnement L'approche opérationnelle est la fonction de corrélation à exécuter dans le processus de collaboration
goexit() Après avoir exécuté la méthode d'affaires dans la pile de co - processus , Et se repliera sur goexitDans la méthode,Appelé àgoexit1Utilisermcall(mcall Un autre travail est de changer de pile )Appelezgoexit0, Réinitialiser les paramètres liés à l'accord ,Puis appelezscheduleFonctions

Ce qui précède a été exécuté avec succès sur le thread , Mais actuellement en usage pratique , En fait, c'est une boucle multithreadée ,Comme le montre la figure ci - dessous:
Insérer la description de l'image ici
Mais ce Multithreading aura des problèmes de concurrence pour obtenir un co - thread , Donc la présence d'une serrure dans ce processus . Cette boucle de fil ressemble beaucoup à Pool de Threads, Le système d'exploitation n'est pas au courant de l'existence d'un programme de collaboration , L'autre est d'exécuter un cycle de programmation pour OrdreExécution de l'accord.

Mais les boucles de fil que nous avons apprises ici font que les collaborations ne peuvent être exécutées que séquentiellement , Cela signifie que si le nombre de fils dans le système est déterminé , L'utilisation de cette boucle de thread ne peut effectuer que des co - threads égaux au nombre de Threads dans le système en même temps , En un sens, c'est encore une exécution séquentielle . Et dans une boucle multithreadée , Le thread doit obtenir des informations sur le co - thread de la file d'attente pour exécuter la tâche de co - thread , Il faut saisir la serrure , Cela peut également causer des problèmes .

G-M-PModèle de programmation

Dans cette partie, nous nous concentrons sur les problèmes que nous avons mentionnés ci - dessus avec les boucles multithreadées , Lorsque plus d'un thread vient pour obtenir une tâche de collaboration globale , Il faut souvent saisir la serrure , Cela rend possible un conflit de serrures ,Comme le montre la figure ci - dessous:

Insérer la description de l'image ici
La solution consiste essentiellement à réduire au minimum le nombre de Threads qui volent des serrures dans un environnement global , Au lieu de cela, exécutez des tâches de collaboration sans verrouillage local . Le terme technique de cette pensée est appelé file d'attente locale , C'est de permettre au Thread de saisir plusieurs co - threads à la fois après avoir saisi la serrure , Lier ces collisions aux files d'attente locales , Une fois que toutes les tâches saisies ont été exécutées , Pour saisir la serrure globale , Cela évite une partie de l'opération de verrouillage .

Insérer la description de l'image ici

Ce qui suitG-M-P Le modèle de programmation est go Modèle d'ordonnancement spécifique pour résoudre les conflits de serrures , Parmi eux G Il s'agit d'une structure de co - intégration g,M Se réfère à la structure du fil m,P C'est aussi une structure , En fait, c'est une file d'attente locale . Les membres de cette structure sont très complexes , Nous examinons principalement une partie des membres associés au modèle d'ordonnancement .

Insérer la description de l'image ici

Variable membreSens
MThreads associés
runqheadPointeur d'en - tête pour la file d'attente
runqtailPointeur de queue pour la file d'attente
runnext Prochain pointeur de co - parcours disponible

Ensuite, résumonsPLe rôle de:

  • MEtGIntermédiaire entre, On peut comprendre ça comme un chargeur
  • P Tenir quelques G, Faire chaque acquisition G Pas besoin de chercher partout
  • Réduit considérablement les situations de conflit simultané

Attention!:

  1. Si la file d'attente locale et la file d'attente globale d'un thread n'ont pas de co - thread à exécuter , Le thread va à un autre thread “Voler”Co - Process, Pour augmenter l'utilisation des fils .
  2. Si vous créez un nouvel accord , Le système cherchera au hasard une file d'attente locale , Placez le nouvel accord sur PDerunnext Faire des files d'attente (Ingo La priorité de la nouvelle collaboration est élevée ), Si la file d'attente locale est pleine , Ce nouvel accord sera mis en file d'attente globale .

Co - processus simultané

Nous avons utilisé le modèle d'ordonnancement pour résoudre le problème de verrouillage des boucles de thread , Il reste une question sur la façon de rendre les coproductions simultanées , Cette question à première vue, il est facile de penser qu'il n'y a pas de problème , Mais en fait, ça va causer Le problème de la faim . Ce problème fait référence au temps excessif qu'il faut pour qu'un thread exécute un certain co - thread , Échec de l'exécution d'un programme de coopération qui rend certains temps sensibles dans la file d'attente .

L'idée de base est que lorsque l'accord est exécuté pendant un certain temps, la tâche actuelle est provisoire , Effectuer des tâches de coordination subséquentes , Empêcher l'échec de l'exécution du Ctrip sensible au temps .Comme le montre la figure ci - dessous:

Insérer la description de l'image ici
Lorsque le co - travail dans le thread actuel est une tâche de longue durée , Pour le moment, sauvegardez d'abord l'état de fonctionnement du Programme coopératif, c'est - à - dire la protection du site , Mettez - le dans la file d'attente locale si vous avez besoin de continuer plus tard , L'affichage est inactif sans exécution ,Puis sautez directement àscheduleEn fonction.

Cela fait de la file d'attente locale une petite boucle , Mais si la file d'attente locale des Threads dans le système actuel a une tâche de collaboration énorme , Alors tous les Threads seront occupés pendant un certain temps , Les tâches dans la file d'attente globale ne fonctionneront pas longtemps , Cette question est aussi appelée Problème de faim dans la file d'attente globale , La solution est que lorsque la file d'attente locale tourne , Extraire une tâche de la file d'attente globale avec une certaine probabilité , Qu'il participe aussi au cycle local .

Ça semble parfait , Mais en fait, quand le co - programme fonctionne , Il est difficile d'interrompre la Mission de l'Association ,La solution est la suivante::

  1. Suspension active :goparkMéthodes, Lorsque l'entreprise appelle cette méthode, le thread retourne directement à schedule Fonction et basculer la pile de co , L'accord en cours d'exécution sera en attente , L'horaire en attente n'a pas pu entrer immédiatement dans la file d'attente des tâches . Le programmeur ne peut pas invoquer activement goparkFonctions,Mais on peut passer parSleepÉquivalentgopark Une fonction pour suspendre activement ,Sleep Après cinq secondes, le système change l'état d'attente de la tâche en état d'exécution dans la file d'attente .
  2. Quand l'appel système est terminé :go Le programme est en cours d'exécution Appel système, Alors quand l'appel sous - jacent du système est terminé, il est appelé exitsyscallFonctions, Le thread cessera d'exécuter le co - thread actuel , Mettre l'accord actuel dans la file d'attente .
  3. Préemption des étiquettes morestack(): Cette méthode est appelée chaque fois qu'une fonction saute , Il est destiné à vérifier si l'espace actuel de la pile de co - processus a suffisamment de mémoire , Si ce n'est pas suffisant, Agrandissez l'espace de la pile . Lorsque le système surveille le fonctionnement du programme de coopération au - delà de 10ms,Juste...g.stackguard0Set As0xfffffade( La valeur est un drapeau préemptif ), Laissez le programme exécuter seulement morestack La fonction détermine si gDansstackguard Set to preempt , Si c'est marqué pour préemption ,Je reviens.scheduleMéthodes, Et remettre l'accord actuel dans la file d'attente .

Programmation préventive basée sur le signal

Lorsque le programme ne peut pas être suspendu activement pendant l'exécution , Moins vous pouvez faire d'appels système , Et quand un appel de fonction ne peut pas être fait , C'est - à - dire que les solutions ci - dessus à la concurrence de co - processus ne fonctionnent pas ,Qu'est - ce qu'on va faire? Nous proposons donc une programmation préventive basée sur le signal . Le signal ici est en fait un signal de fil , Il existe de nombreux moyens de communication sous - jacents basés sur le signal dans le système d'exploitation , Et nos fils peuvent enregistrer les fonctions de traitement des signaux correspondants .

Idées de base:

  • InscriptionSIGURGSignal( Ce signal est rarement utilisé ailleurs )Fonction de traitement pour
  • GCAu travail(GC Le travail signifie que certains fils se sont arrêtés ), Envoyer un signal au fil cible
  • Le fil a reçu le signal ,Déclenchez l'ordonnancement.

Insérer la description de l'image ici

QuandGC Après le signal , Le thread qui travaille actuellement sur la tâche de collaboration exécutera doSigPreemptFonctions, Remettre l'accord actuel dans la file d'attente ,RappelscheduleFonctions.

Mentions de copyright
Auteur de cet article [Bonjour tout le monde. Je suis un bon camarade de classe.],Réimpression s’il vous plaît apporter le lien vers l’original, merci
https://fra.chowdera.com/2022/204/202207231539284393.html

Recommandé au hasard