Parfois, je dois utiliser std::thread
pour accélérer mon application. Je sais aussi qu'il join()
attend la fin d'un fil. C'est facile à comprendre, mais quelle est la différence entre appeler detach()
et ne pas l'appeler?
Je pensais que sans detach()
, la méthode du thread fonctionnera en utilisant un thread indépendamment.
Ne pas se détacher:
void Someclass::Somefunction() {
//...
std::thread t([ ] {
printf("thread called without detach");
});
//some code here
}
Appel avec détachement:
void Someclass::Somefunction() {
//...
std::thread t([ ] {
printf("thread called with detach");
});
t.detach();
//some code here
}
std
et lesboost
threads ontdetach
et ontjoin
modelé de près les threads POSIX.Réponses:
Dans le destructeur de
std::thread
,std::terminate
est appelé si:t.join()
)t.detach()
)Ainsi, vous devez toujours soit
join
oudetach
un thread avant que les flux d'exécution n'atteignent le destructeur.Lorsqu'un programme se termine (c'est-à-dire qu'il
main
retourne), les threads détachés restants s'exécutant en arrière-plan ne sont pas attendus; au lieu de cela, leur exécution est suspendue et leurs objets locaux de thread détruits.Fondamentalement, cela signifie que la pile de ces threads n'est pas déroulée et que certains destructeurs ne sont donc pas exécutés. Selon les actions que ces destructeurs étaient censés entreprendre, cela pourrait être une situation aussi grave que si le programme s'était écrasé ou avait été tué. Espérons que le système d'exploitation libérera les verrous sur les fichiers, etc., mais vous pourriez avoir corrompu la mémoire partagée, les fichiers à moitié écrits, etc.
Alors, devriez-vous utiliser
join
oudetach
?join
detach
la source
Vous devriez appeler
detach
si vous n'attendez pas que le thread se termine,join
mais le thread continuera à fonctionner jusqu'à ce que ce soit terminé, puis se terminera sans que le thread principal l'attende spécifiquement.detach
va essentiellement libérer les ressources nécessaires pour être en mesure de mettre en œuvrejoin
.C'est une erreur fatale si un objet thread termine sa vie et que ni
join
nidetach
n'a été appelé; dans ce casterminate
est invoquée.la source
Lorsque vous détachez le fil, cela signifie que vous n'êtes pas obligé de le
join()
faire avant de quittermain()
.La bibliothèque de threads attendra chaque thread ci-dessous , mais vous ne devriez pas vous en soucier.
detach()
est principalement utile lorsque vous avez une tâche qui doit être effectuée en arrière-plan, mais que vous ne vous souciez pas de son exécution. C'est généralement le cas pour certaines bibliothèques. Ils peuvent créer silencieusement un thread de travail en arrière-plan et le détacher afin que vous ne le remarquiez même pas.la source
Cette réponse vise à répondre à la question dans le titre, plutôt qu'à expliquer la différence entre
join
etdetach
. Alors, quand faut-std::thread::detach
il l'utiliser?Dans le code C ++ correctement entretenu,
std::thread::detach
ne doit pas du tout être utilisé. Le programmeur doit s'assurer que tous les threads créés se terminent correctement en libérant toutes les ressources acquises et en exécutant les autres actions de nettoyage nécessaires. Cela implique que renoncer à la propriété des threads en appelantdetach
n'est pas une option etjoin
doit donc être utilisé dans tous les scénarios.Cependant, certaines applications reposent sur des API anciennes et souvent mal conçues et prises en charge qui peuvent contenir des fonctions de blocage indéfiniment. Déplacer les invocations de ces fonctions dans un thread dédié pour éviter de bloquer d'autres éléments est une pratique courante. Il n'y a aucun moyen de faire en sorte qu'un tel thread se termine correctement, donc l'utilisation de
join
mènera simplement au blocage du thread principal. C'est une situation dans laquelle l'utilisationdetach
serait une alternative moins mauvaise, par exemple, à l'allocation d'unthread
objet avec une durée de stockage dynamique, puis à le divulguer intentionnellement.la source
Selon cppreference.com :
Par exemple:
Remarquez la variable locale:, tant
my_thread
que la durée de vie demy_thread
est terminée, le destructeur destd::thread
sera appelé, etstd::terminate()
sera appelé dans le destructeur.Mais si vous utilisez
detach()
, vous ne devriez plus utilisermy_thread
, même si la durée de vie demy_thread
est terminée, rien n'arrivera au nouveau thread.la source
&
dans la capture lambda, vous utilisez les variables de la portée englobante par référence - vous feriez donc mieux de vous assurer que la durée de vie de tout ce que vous référencez est plus longue que la durée de vie de votre thread.