it-swarm.com.de

C++ 11: Was passiert, wenn Sie join () nicht für std :: thread aufrufen

Unten angegeben:

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 wird nach 5 Sekunden beendet. Was passiert mit th1, der noch ausgeführt wird?

Wird die Ausführung bis zur Fertigstellung fortgesetzt, auch wenn das in main definierte th1-Threadobjekt außerhalb des Gültigkeitsbereichs liegt und zerstört wird?

Sitzt th1 einfach dort, wenn die Ausführung abgeschlossen ist, oder wird es irgendwie bereinigt, wenn das Programm beendet wird?

Was wäre, wenn der Thread in einer Funktion erstellt wurde, nicht main - bleibt der Thread in der Nähe, bis das Programm beendet wird oder die Funktion den Funktionsumfang verlässt?

Ist es sicher, einfach join für einen Thread nicht aufzurufen, wenn Sie eine Art Timeout-Verhalten für den Thread wünschen?

28
kiki

Wenn Sie beim Aufruf des Destruktors keinen Thread getrennt oder einem Thread beigetreten sind, ruft er std::terminate auf. Dies können Sie sehen, indem Sie zum draft C++ 11-Standard gehen wir sehen diesen Abschnitt 30.3.1.3Thread-Destruktor sagt:

Wenn joinable (), ruft std :: terminate () auf. Ansonsten hat keine Wirkung. [ Anmerkung: Entweder ein Joinable () -Thread wird implizit in .__ getrennt oder verbunden. Sein Destruktor kann dazu führen, dass Fehler in Bezug auf Fehler (.... trennen) oder Leistung (. für Join) nur schwer gefunden werden können, wenn ein Ausnahme wird ausgelöst. Der Programmierer muss also sicherstellen, dass die Destruktor wird nie ausgeführt, solange der Thread noch verbunden werden kann. -Ende Hinweis ]

als Grund für dieses Verhalten finden wir eine gute Zusammenfassung in (Nicht) mit std :: thread

Warum muss der Destruktor eines joinfähigen Threads .__ aufrufen. std :: beenden Immerhin könnte der Destruktor mit dem Kind verbunden werden Thread, oder es könnte sich vom untergeordneten Thread lösen, oder es kann abgebrochen werden der Faden. Kurz gesagt, Sie können den Destruktor nicht mitmachen, da dies ____ wäre. führt zu unerwartetem (im Code nicht explizit angegebenem) Programm einfrieren, falls f2 wirft.

und ein Beispiel folgt und sagt auch:

Sie können nicht getrennt werden, da dies die Situation gefährden könnte, wenn der Haupt-Thread Lässt den Bereich, in dem der untergeordnete Thread gestartet wurde, und das untergeordnete Element Thread läuft weiter und hält Verweise auf den Gültigkeitsbereich, der bereits vorhanden ist Weg.

Der Artikel referenziert N2802: Ein Plädoyer für die Neueinschätzung der Ablösung bei der Zerstörung von Threadobjekten Dies ist ein Argument gegen den vorherigen Vorschlag, bei dem die Vernichtung bei der Zusammenfügung erfolgte, und stellt fest, dass eine der beiden Alternativen beitreten würde, die beitreten könnten führen zu Deadlocks Die andere Alternative ist das, was wir heute haben, das std::terminate bei der Zerstörung ist, wenn es zusammengefügt werden kann.

19
Shafik Yaghmour

std::thread::~thread()

Wenn * dies einen zugeordneten Thread hat (joinable() == true), wird std::terminate() aufgerufen

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

Dies bedeutet, dass ein Programm wie dieses überhaupt nicht wohlgeformt oder sicher ist.

Beachten Sie jedoch, dass boost::thread::~thread() in diesem Fall detach() aufruft. (Wie Benutzer dyp in Kommentaren angegeben hat, ist dieses Verhalten in neueren Versionen veraltet.)

Sie können dies jederzeit mit RAII umgehen. Wickeln Sie Ihren Faden einfach in eine andere Klasse, die das gewünschte Verhalten bei der Zerstörung zeigt.

In C++ 11 müssen Sie explizit angeben, was passiert, wenn der neu erstellte Thread den Gültigkeitsbereich verlässt (unser dtor heißt). Manchmal, wenn wir sicher sind, dass der Haupt-Thread fortgesetzt wird und unsere Threads als "Pipeline" fungieren, ist es sicher, sie zu "trennen". und manchmal, wenn wir darauf warten, dass unsere WORKER-Threads ihre Vorgänge abschließen, "joinen" wir sie.

Wie das sagt, muss der Programmierer sicherstellen, dass der Destruktor niemals ausgeführt wird, während der Thread noch verbunden werden kann.

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

1
mkr