Pour qu'il y ait une jointure, deux fils sont nécessaires. Un thread appelle l'autre thread. Rejoindre un fil signifie que, alors que le thread d'appel est en cours d'exécution, il s'arrêterait à une position et attendrait que le fil appelé terminer son exécution (jusqu'à sa fin), avant de continuer sa propre exécution. À la position où le fil s'arrête, il y a une expression de jointure. Un tel arrêt est appelé blocage.
Si le fil appelé prend trop de temps à terminer et a probablement fait ce que le fil d'appel s'attendait, alors le fil d'appel peut le détacher. Après le détachement, si le thread appelé se termine après le thread d'appel, il ne devrait y avoir aucun problème. Le détachement signifie briser la jointure (lien).
Rappel
Un thread est une fonction de niveau supérieur qui a été enfermée dans un objet de thread, instanciée à partir de la classe de threads. Instanciation du thread avec la fonction de niveau supérieur signifie appeler la fonction. Voici un programme de discussion simple, avec l'instruction JOIN:
#inclure
#inclure
Utilisation de Namespace Std;
void func ()
couter <<"… from thread!" <<'\n';
int main()
thread thd (func);
THD.rejoindre();
/ * instructions * /
retour 0;
Il y a deux threads ici: l'objet, le THD et la fonction principale (). La fonction principale est comme le fil principal. Notez l'inclusion de la bibliothèque de threads. La sortie est:
… Du fil!
À l'invite de commande, un programme C ++ 20 avec des threads doit être commandé comme suit, pour le compilateur G ++:
g ++ -std = c ++ 2a échantillon.CC -lpthread -O échantillon.exe
Contenu de l'article
Syntaxe detach ()
La syntaxe detach () est simple; c'est:
threadobject.détacher()
Cette fonction membre de l'objet thread renvoie vide. ThreadObject est l'objet de thread du thread dont la fonction est en cours d'exécution. Lorsque la fonction d'un thread est en cours d'exécution, le thread est appelé le thread exécutif.
Un fil ne peut être détaché qu'après avoir été rejoint; Sinon, le fil est déjà à l'état détaché.
Ambiguïté de détacher dans le corps du fil d'appel
Dans le programme suivant, le fil appelé est détaché dans le corps du fil d'appel:
#inclure
#inclure
#inclure
Utilisation de Namespace Std;
String Globl = String ("sur Terre!");
void func (String st)
String fin = "Living" + St;
couter <
int main()
Thread Thr (Func, Globl);
thr.rejoindre();
thr.détacher();
retour 0;
La sortie de l'ordinateur de l'auteur lors de l'exécution était:
Vivre sur Terre!
Terminé appelé après avoir lancé une instance de 'std :: system_error'
quoi (): argument non valide
Avorté (noyau déversé)
La sortie appropriée attendue devrait être juste:
Vivre sur Terre!
Lorsqu'un fil met fin à son exécution, l'implémentation libère toutes les ressources qu'il possédait. Lorsqu'un fil est joint, le corps du fil d'appel attend à ce point jusqu'à ce que le thread appelé termine son exécution, alors le corps du fil d'appel continue sa propre exécution.
Le problème de la présence de la sortie supplémentaire est que, bien que le thread appelé pourrait avoir terminé sa tâche qui lui a été donnée, ses ressources n'avaient pas été enlevées, mais la fonction detach () a provoqué le fait que le corps de la fonction d'appel continue d'exécuter. En l'absence de la fonction detach (), le thread appelé aurait terminé, ainsi que toutes ses ressources enlevées; Et la sortie aurait été la simple ligne attendue.
Pour convaincre davantage le lecteur, considérez le programme suivant, qui est le même que ce qui précède, mais avec les déclarations join () et detach () a commenté:
#inclure
#inclure
#inclure
Utilisation de Namespace Std;
String Globl = String ("sur Terre!");
void func (String st)
String fin = "Living" + St;
couter <
int main()
Thread Thr (Func, Globl);
// thr.rejoindre();
// thr.détacher();
retour 0;
La sortie de l'ordinateur de l'auteur est:
terminer appelé sans exception active
Avorté (noyau déversé)
La fonction principale () a traversé sa fin sans attendre que le fil fasse quoi que ce soit. Et donc, le thread n'a pas pu afficher sa sortie.
Nom du thread à la portée globale
Un fil peut être instancié à la portée mondiale. Le programme suivant illustre ceci:
#inclure
#inclure
Utilisation de Namespace Std;
Thread Thr;
void func ()
couter <<"the first line" <couter <<"the second line" <
int main()
thr = thread (func);
thr.rejoindre();
retour 0;
La sortie est:
la première ligne
la deuxième ligne
Avant la fonction, Func () est défini dans le programme; il y a la déclaration,
Thread Thr;
qui instancie le fil, thr. À ce stade, THR n'a pas de fonction correspondante. Dans la fonction Main (), la première instruction est:
thr = thread (func);
Le côté droit de cette instruction crée un thread sans nom et attribue le thread à la variable de thread, thr. De cette façon, THR acquiert une fonction. La déclaration suivante rejoint le fil appelé.
Détacher dans le fil appelé
Une meilleure façon de détacher un fil est de le faire dans le corps du fil appelé. Dans ce cas, l'objet de thread devrait être créé dans la portée globale, comme illustré ci-dessus. Ensuite, la déclaration de détachage sera dans le corps du fil appelé, où le détachement devrait avoir lieu. Le programme suivant illustre ceci:
#inclure
#inclure
Utilisation de Namespace Std;
Thread Thr;
void func ()
couter <<"the first line" <thr.détacher();
couter <<"the second line" <
int main()
thr = thread (func);
thr.rejoindre();
couter <<"main() function line" <retour 0;
La sortie est:
la première ligne
la deuxième ligne
ligne de fonction main ()
Aucun message d'erreur n'a été émis au moment de l'exécution. L'instruction join () s'attendait à ce que le thread s'exécute avant que le corps de fonction principal () puisse continuer. Cela s'est produit malgré le fait que le fil appelé a été détaché au milieu de son exécution, avec la déclaration,
thr.détacher();
Et donc la fonction principale () (thread principal) s'est poursuivie une fois le thread appelé terminé, avec toutes ses ressources publiées par l'implémentation. Dans la seconde moitié du fil appelé, le fil appelé était déjà détaché, bien que le fil d'appel attendait toujours.
Le programme commence par l'inclusion de la bibliothèque iOStream pour l'objet cout. Ensuite, il y a l'inclusion de la bibliothèque de threads, qui est un must. Ensuite, il y a l'instanciation du thread, thr, sans fonction. La fonction qu'il utilisera est définie juste après. Cette fonction a la déclaration détachée de l'objet, thr dans son corps.
Dans le corps de fonction Main (), la première instruction crée un thread d'une fonction mais sans nom. Ce thread est ensuite affecté à Thr. Ainsi, Thr a maintenant une fonction, avec l'avantage qu'il a été créé dans la portée mondiale, afin qu'il puisse être vu dans Func ().
L'instruction suivante rejoint le corps de fonction de la fonction principale () au thread appelé. Le thread a été appelé dans la première déclaration de la fonction principale (). À ce stade, le corps de fonction Main () attend que le fil appelé fonctionne jusqu'à sa fin et toutes ses ressources libérées, bien qu'elle ait été détachée au milieu. La fonction join () fait son devoir tant que tout ce qui est à l'intérieur du fil appelé est légitime.
Et ainsi l'exécution se poursuit avec la fonction principale après que le thread appelé est sorti avec succès, comme prévu (avec toutes ses ressources publiées). C'est pourquoi,
«Ligne de fonction main ()»
est sorti après toutes les sorties du thread appelé.
Conclusion
Le détachement d'un thread signifie que le thread appelé peut continuer à s'exécuter, tandis que le thread appelé peut également continuer à exécuter. C'est-à-dire que le fil d'appel ne continue plus d'attendre (bloc), après avoir rejoint. Cela peut augmenter la vitesse des deux fils, leur permettant de s'exécuter en parallèle et d'augmenter ainsi la vitesse de l'ensemble du programme. Dans ce cas, il est préférable de détacher le fil dans son corps, où la communication entre eux ne se produira plus. De plus, pour y parvenir, laissez la variable de thread être créée dans la portée globale sans sa fonction. Dans la fonction principale () du programme C ++, un thread anonyme, avec la fonction d'intérêt, peut être créé et affecté à la variable de thread. Cette étape appelle la fonction du thread, et ainsi, appelle le thread.
Ainsi, après la déclaration de détachement, la déclaration join () n'a plus son rôle normal d'attente (bloquant le fil d'appel), bien qu'il puisse toujours attendre. Il n'est pas recommandé de détacher le fil appelé à partir du fil d'appel.