2016-10-19 4 views
3

Wenn ich eine std::thread im Konstruktor von Bar abspinnt, wann hört es auf zu laufen? Ist es garantiert zu stoppen, wenn die Bar Instanz zerstört wird?Std :: Thread-Thread in Objekt ausgegliedert, wann endet es?

class Bar { 

public: 

Bar() : thread(&Bar:foo, this) { 
} 

... 

void foo() { 
    while (true) {//do stuff//} 

} 

private: 
    std::thread thread; 

}; 

EDIT: Wie richtig beenden ich die std::thread im Destruktor?

+1

Siehe http://stackoverflow.com/a/13984169/12711 –

+0

@kfsone danke für den Kommentar. Könnten Sie etwas mehr angeben, auf das undefiniertes Verhalten Thread (& Bar :: foo, das) auf – user695652

+0

@ user695652 angewiesen ist, ist es generell gefährlich, 'this' (oder Objektmitglieder) in der Initialisierungsliste eines Konstruktors zu übergeben. Ihr Objekt enthält nur den Thread, so dass es in diesem Beispiel keinen Schaden gibt, aber wenn es mehr Felder hat, sollten Sie darauf achten, dass Ihr Thread ausgeführt werden könnte, bevor Ihr Objekt vollständig aufgebaut ist. – zneak

Antwort

2

Wenn ich einen std :: -Thread im Konstruktor von Bar abspinnt, wann hört es auf zu laufen?

Der Thread wird so lange ausgeführt, wie die ausführbare Datei ausgeführt wird, oder das Programm wird beendet.

Wird garantiert gestoppt, wenn die Bar-Instanz zerstört wird?

Nr Um das zu gewährleisten, rufen std::thread::join in Bar destructor.

Eigentlich, wenn Sie nicht thread::join oder thread::detach vor Bar::~Bar nennen haben, als Ihre Anwendung durch den Aufruf automatisch std::terminate beendet werden. so müssen Sie müssen entweder join anrufen (bevorzugt) oder detach (weniger empfohlen).

Sie wollen auch therad::join auf dem Objekt destructor nennen, weil der erzeugte Thread auf das Objekt verlässt sich am Leben zu sein, wenn das Objekt zerstört wird, während der Thread auf das Objekt arbeitet - Sie destructed Objekt verwenden und Sie werden haben undefiniertes Verhalten in Ihrem Code.

+0

danke für Ihre Antwort. Ich verstehe den letzten Teil nicht, wenn du thread :: join oder thread :: detach nicht aufgerufen hast, also in meinem obigen Beispiel, was passiert mit dem Thread? – user695652

+0

Wenn Sie 'thread :: join' oder' thread :: detach' nicht aufrufen ** und ** der Destruktor des Threads gestartet wird, wird die gesamte Anwendung beendet. –

+0

gut, irgendwie. "Absturz" ist, wenn das Betriebssystem tatsächlich Ihren Prozess tötet. Hier endet das Programm selbst. Natürlich definiert der Standard nicht wirklich den Begriff "Absturz" –

0

Kurze Antwort: Ja und Nein. Ja, endet der Thread, aber nicht auf die übliche Weise (den Thread zu töten), sondern durch den Haupt-Thread aufgrund eines Aufrufs std::terminate.

Lange Antwort: Der Thread kann nur dann sicher zerstört werden, wenn die zugrunde liegende Funktion (Thread) die Ausführung beendet hat. Dies kann auf 2 Arten

  • Aufruf join() erfolgen, was wartet auf den Thread zu beenden (in Ihrem Fall nie)
  • detach() Aufruf, die den Faden von dem Haupt-Thread ablöst (in diesem Fall der Der Thread endet, wenn der Hauptthread schließt - wenn das Programm beendet wird.wenn alle those conditions

Wenn der Destruktor aufgerufen wird, nicht gelten, dann wird std::terminate genannt:

  • wurde default-konstruiert

  • wurde von

    bewegt
  • join() wurde

  • 0 genannt
  • detach() hat

0

Die C++ Einfädeln Einrichtungen tun nicht umfassen einen eingebauten Mechanismus zum Abschließen eines Thread aufgerufen wurde. Stattdessen müssen Sie selbst entscheiden: a) einen Mechanismus, um dem Thread zu signalisieren, dass er beendet werden sollte, b) dass es Ihnen egal ist, dass der Thread mitten in der Operation abgebrochen wird, wenn der Prozess beendet wird und das Betriebssystem seine Threads einfach nicht mehr ausführt Mehr.

Das Objekt std::thread ist nicht der Thread selbst, sondern ein undurchsichtiges Objekt, das einen Deskriptor/Handle für den Thread enthält, also theoretisch zerstört werden könnte, ohne den Thread zu beeinflussen, und es gab Argumente für und gegen die automatische Beendigung des Threads . Stattdessen wurde als ein Kompromiss gemacht, dass das Zerstören eines std::thread Objekts, während der Thread ausgeführt und angehängt wurde, zum Beenden der Anwendung führen würde.

Als Ergebnis Darin Destruktor gibt es einige Code wie folgt:

~thread() { 
    if (this->joinable()) 
     std::terminate(...); 
} 

Hier ist ein Beispiel für eine einfache atomare Variable und im Thread für sie zu prüfen. Für komplexere Fälle müssen Sie möglicherweise einen condition_variable oder einen anderen komplexeren Signalmechanismus in Betracht ziehen.

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

class S { 
    std::atomic<bool> running_; 
    std::thread thread_; 
public: 
    S() : running_(true), thread_([this]() { work(); }) {} 
    void cancel() { running_ = false; } 
    ~S() { 
     if (running_) 
      cancel(); 
     if (thread_.joinable()) 
      thread_.join(); 
    } 
private: 
    void work() { 
     while (running_) { 
      std::this_thread::sleep_for(std::chrono::milliseconds(500)); 
      std::cout << "tick ...\n"; 
      std::this_thread::sleep_for(std::chrono::milliseconds(500)); 
      std::cout << "... tock\n"; 
     } 
     std::cout << "!running\n"; 
    } 
}; 

int main() 
{ 
    std::cout << "main()\n"; 
    { 
     S s; 
     std::this_thread::sleep_for(std::chrono::milliseconds(2750)); 
     std::cout << "end of main, should see a tock and then end\n"; 
    } 
    std::cout << "finished\n"; 
} 

Live-Demo: http://coliru.stacked-crooked.com/a/3b179f0f9f8bc2e1

Verwandte Themen