1
votes

Pourquoi le thread détaché en C ++ 11 peut-il s'exécuter même si le destructeur a été appelé

Je viens de lire la documentation sur std :: thread.detach () en C ++ 11.

Voici mon test:

#include <iostream>
#include <thread>
#include <chrono>

static int counter = 0;    

void func()
{
    while (true) {
        std::cout<<"running..."<<std::endl;
        std::cout<<counter++<<std::endl;
        std::this_thread::sleep_for(std::chrono::milliseconds(1000));
    }
}


int main()
{
    {
        std::thread t(func);
        t.detach();
    } // t is released after this line
    // t has died, so who is holding the resources of the detached thread???

    std::cin.get();

    return 0;
}

Ce code fonctionne comme prévu. Il semble donc que le thread puisse continuer à fonctionner même si son destructeur a été appelé. Est-ce vrai?

Si c'est vrai, qui sur terre détient les ressources du thread après la libération de l'objet t? Existe-t-il un mécanisme pour conserver les ressources, par exemple, un objet anonyme caché?


0 commentaires

3 Réponses :


0
votes

Les threads d'exécutions existent indépendamment des objets thread que vous utilisez pour les gérer en C ++. Lorsque vous détachez un objet thread, le thread d'exécution continue de s'exécuter, mais l'implémentation (généralement en combinaison avec le système d'exploitation) en est responsable.


0 commentaires

1
votes

Vous avez raison de dire que le thread continue de fonctionner s'il est détaché après le destructeur du thread.

Personne sur terre ne détient les ressources (sauf si vous prenez des dispositions pour que quelqu'un le fasse). Cependant, lorsque votre application se termine, le processus d'arrêt de l'application mettra fin au thread.

On peut encore s'arranger pour communiquer avec et "attendre" un thread détaché. En substance, join () est une API pratique pour que vous n'ayez pas à faire quelque chose comme ceci:

#include <atomic>
#include <chrono>
#include <iostream>
#include <thread>

static int counter = 0;    

std::atomic<bool> time_to_quit{false};
std::atomic<bool> has_quit{false};

void func()
{
    while (!time_to_quit) {
        std::cout<<"running..."<<std::endl;
        std::cout<<counter++<<std::endl;
        std::this_thread::sleep_for(std::chrono::milliseconds(1000));
    }
    has_quit = true;
}


int main()
{
    {
        std::thread t(func);
        t.detach();
    } // t is released after this line

    using namespace std::chrono_literals;
    std::this_thread::sleep_for(3s);
    time_to_quit = true;
    while (!has_quit)
        ;
    std::cout << "orderly shutdown\n";
}


0 commentaires

3
votes

En C ++, std :: thread ne gère pas le thread d'exécution lui-même. C ++ n'a pas du tout de contrôle pour gérer le thread d'exécution.

std :: thread gère le handle de thread - l'identifiant d'un thread ( thread_t dans le monde Posix, qui était en grande partie un modèle pour std :: thread ). Un tel identifiant est utilisé pour communiquer (comme en control ) avec le thread, mais en C ++, le seul moyen de communication standard serait de rejoindre le thread (qui attend simplement pour l'achèvement du thread) ou détachez-vous de celui-ci.

Lorsque le destructeur de std :: thread est appelé, le handle de thread est également détruit et aucun contrôle supplémentaire du thread n'est possible. Mais le fil d'exécution lui-même reste et continue d'être géré par l'implémentation (ou, plus précisément, le système d'exploitation).

Veuillez noter que pour les threads non détachés, les destructeurs de std :: thread lèvent une exception si le thread n'a pas été joint. Il s'agit simplement d'une protection contre les développeurs qui perdent accidentellement la poignée de thread alors qu'ils n'avaient pas l'intention de le faire.


0 commentaires