2014-12-10 7 views
18

Da unten:C++ 11: Was passiert, wenn Sie nicht beitreten nennen() für std :: thread

void test() 
{ 
    std::chrono::seconds dura(20); 
    std::this_thread::sleep_for(dura); 
} 

int main() 
{ 
    std::thread th1(test); 
    std::chrono::seconds dura(5); 
    std::this_thread::sleep_for(dura); 
    return 0; 
} 

main nach 5 Sekunden verlassen wird, was zu th1 passieren wird, dass nach wie vor ist die Ausführung?

Wird die Ausführung bis zur Fertigstellung fortgesetzt, auch wenn das th1 Thread-Objekt, das Sie in main definiert haben, den Geltungsbereich verlässt und zerstört wird?

Sitzt th1 einfach dort, nachdem es fertig ausgeführt wurde oder irgendwie aufgeräumt wird, wenn das Programm beendet wird?

Was ist, wenn der Thread in einer Funktion erstellt wurde, nicht main - bleibt der Thread so lange bestehen, bis das Programm beendet wird oder wenn die Funktion den Gültigkeitsbereich verlässt?

Ist es sicher, nicht einfach join für einen Thread aufzurufen, wenn Sie eine Art von Timeout-Verhalten auf dem Thread wollen?

+0

Warum versuchst du es nicht? – Drop

+14

@Drop Weil das keine zuverlässige Möglichkeit ist, über * Garantien * zu lernen. – dyp

+0

@dyp keine Frage auf Stackoverflow ist. Indem er dieses 5-Zeilen-Beispiel kompilierte und ausführte, konnte er wenigstens einen Hinweis finden. Es gibt nur eine Garantiequelle - einen Standard. – Drop

Antwort

16

Wenn Sie nicht gelöst haben oder einen Faden verbunden, wenn der destructor es std::terminate nennen genannt wird, können wir dies sehen, indem auf die draft C++11 standard gehen wir sehen, dass Abschnitt 30.3.1.3Faden destructor sagt:

Wenn joinable(), ruft std :: terminate() auf. Ansonsten hat das keine Auswirkungen. [ ] Hinweis: Das implizite Trennen oder Verknüpfen eines Joinable() - Threads in seines Destruktors kann zu schwer zu debuggenden Korrektheit (für trennen) oder Leistung (für Join) führen, die nur auftreten, wenn eine Ausnahme ausgelöst wird. Daher muss der Programmierer sicherstellen, dass der Destruktor niemals ausgeführt wird, solange der Thread noch verbindbar ist. -Ende note]

als eine Begründung für dieses Verhalten, das wir eine gute Zusammenfassung in (Not) using std::thread

Warum die destructor eines joinable Faden std finden können, sind nennen :: kündigen?Schließlich könnte der Destruktor mit dem untergeordneten Thread verbunden werden, oder er könnte sich vom untergeordneten Thread lösen, oder er könnte den Thread abbrechen. Kurz gesagt, Sie können nicht am Destruktor teilnehmen, da dies zu einem unerwarteten (nicht explizit im Code angegebenen) Programm Einfrieren führen würde, falls f2 ausgelöst wird.

und ein Beispiel folgt und sagt auch:

Sie können nicht lösen, wie es die Situation riskieren würde, wo Hauptthread den Umfang verlässt, die das Kind Faden in ins Leben gerufen wurde, und das Kind Faden hält läuft und hält Verweise auf den Bereich, der bereits gegangen ist.

Der Artikel verweist auf N2802: A plea to reconsider detach-on-destruction for thread objects das Argument gegen den früheren Vorschlag ist, die auf Zerstörung lösen war, wenn joinable und es stellt fest, dass eine der beiden Alternativen wäre zu verbinden, die die andere Alternative zu Deadlocks führen könnte, ist, was wir heute haben, welches ist std::terminate auf Zerstörung wenn verbindbar.

5

std::thread::~thread()

* Wenn dies hat ein zugeordnetes Gewinde (joinable() == true), std::terminate()

genannt

Quelle: http://en.cppreference.com/w/cpp/thread/thread/~thread

Dies bedeutet, dass Programm wie dieses überhaupt nicht gut ist, gebildet oder sicher.

Beachten Sie jedoch, dass in diesem Fall boost::thread::~thread() stattdessen detach() aufgerufen wird. (als Benutzer dyp in den Kommentaren erwähnt, dieses Verhalten in neueren Versionen veraltet)

Man könnte dies mit RAII immer umgehen. Wickeln Sie Ihren Thread einfach in eine andere Klasse, die das gewünschte Verhalten bei der Zerstörung hat.

+2

Dieses Verhalten von Boost ist veraltet: http://www.boost.org/doc/libs/1_57_0/doc/html/thread/thread_management.html#thread.thread_management.thread.destructor – dyp

+0

@dyp Cool! Darf ich es in meiner Antwort hinzufügen? ;) – Drop

+1

Nun, natürlich. Deshalb mache ich Kommentare :) – dyp

1

In C++ 11 müssen Sie explizit angeben, was passiert, wenn der neu erstellte Thread den Gültigkeitsbereich verlässt (unser it's dtor wird aufgerufen). Manchmal, wenn wir sicher sind, dass der Hauptthread fortfährt und unsere Threads als "Pipeline" agieren, ist es sicher, sie zu "lösen". und manchmal, wenn wir darauf warten, dass unsere WORKER-Threads ihre Operationen abschließen, "schließen" wir sie ab.

Wie this sagt, muss der Programmierer sicherstellen, dass der Destruktor nie ausgeführt wird, während der Thread noch verbindbar ist.

Geben Sie Ihre Multi-Thread-Strategie an. In diesem Beispiel wird std::terminate() aufgerufen.