Quand dois-je utiliser std::thread::détacher?
Parfois, je dois utiliser std::thread
pour accélérer mon application. Je sais aussi que join()
attend qu'un thread se termine. 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
}
4 réponses
Dans le destructeur de std::thread
, std::terminate
est appelé si:
- , le thread n'a pas été joint (avec
t.join()
) - et n'a pas été détaché non plus (avec
t.detach()
)
Ainsi, vous devriez toujours join
ou detach
un thread avant que les flux d'exécution n'atteignent le destructeur.
Lorsqu'un programme se termine (c'est-à-dire que main
retourne), les threads détachés restants s'exécutant en arrière-plan ne sont pas attendus; à la place, leur exécution est suspendue et leur fil-objets locaux 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 va libérer les verrous sur les fichiers, etc... mais vous pourriez avoir corrompu la mémoire partagée, les fichiers à moitié écrits, etc.
Donc, devriez-vous utiliser join
ou detach
?
- Utiliser
join
- sauf si vous avez besoin de plus de flexibilité et êtes prêt à fournir un mécanisme de synchronisation pour attendre l'achèvement du thread par vous-même , auquel cas vous pouvez utiliser
detach
Vous devriez appeler detach
si vous n'attendez pas que le thread se termine avec join
mais le thread continuera à fonctionner jusqu'à ce qu'il soit terminé, puis se terminera sans que le thread principal l'attende spécifiquement.
detach
fondamentalement, permettra de libérer les ressources nécessaires pour être en mesure de mettre en œuvre join
.
C'est une erreur fatale si un objet thread termine sa vie et que ni join
NI detach
n'a été appelé; dans ce cas, terminate
est invoqué.
Lorsque vous détachez le thread, cela signifie que vous n'avez pas à le join()
avant de quitter main()
.
la bibliothèque de threads attendra réellement chacun de ces threads ci-dessous-main , mais vous ne devriez pas vous en soucier.
detach()
est principalement utile lorsque vous avez une tâche qui doit être faite 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 pour que vous ne le remarquiez même pas.
Selon cppreference.com:
Sépare le thread d'exécution de l'objet thread, permettant exécution pour continuer indépendamment. Toutes les ressources allouées seront libéré une fois le thread sorti.
Après avoir appelé detach
*this
ne possède plus de thread.
Par exemple:
std::thread my_thread([&](){XXXX});
my_thread.detach();
Notez que la variable locale: my_thread
, tandis que la durée de vie de my_thread
est terminée, le destructeur de std::thread
sera appelé, et std::terminate()
sera appelé dans le destructeur.
Mais si vous utilisez detach()
, Vous ne devriez plus utiliser my_thread
, mais si la durée de vie de my_thread
est terminée, rien n'arrivera au nouveau thread.