Manchmal muss ich std::thread
meine Anwendung beschleunigen. Ich weiß auchjoin()
wartet, bis ein Thread abgeschlossen ist. Das ist leicht zu verstehen, aber was ist der Unterschied zwischen Anrufen detach()
und Nichtanrufen?
Ich dachte das ohne detach()
, die Methode des Threads mit einem Thread unabhängig arbeiten wird.
Nicht ablösen:
void Someclass::Somefunction() {
//...
std::thread t([ ] {
printf("thread called without detach");
});
//some code here
}
Anrufen mit Abnehmen:
void Someclass::Somefunction() {
//...
std::thread t([ ] {
printf("thread called with detach");
});
t.detach();
//some code here
}
std
undboost
Threads habendetach
und sindjoin
eng an POSIX-Threads angelehnt.Antworten:
Im Destruktor
std::thread
,std::terminate
wird aufgerufen , wenn:t.join()
)t.detach()
)Daher sollten Sie immer entweder
join
oderdetach
einen Thread verwenden, bevor die Ausführungsflüsse den Destruktor erreichen.Wenn ein Programm beendet wird (dh
main
zurückkehrt), wird nicht auf die verbleibenden getrennten Threads gewartet, die im Hintergrund ausgeführt werden. Stattdessen wird ihre Ausführung angehalten und ihre threadlokalen Objekte zerstört.Entscheidend ist, dass der Stapel dieser Threads nicht abgewickelt wird und daher einige Destruktoren nicht ausgeführt werden. Abhängig von den Aktionen, die diese Destruktoren ausführen sollten, kann dies eine so schlimme Situation sein, als ob das Programm abgestürzt oder getötet worden wäre. Hoffentlich hebt das Betriebssystem die Sperren für Dateien usw. auf, aber Sie könnten den gemeinsam genutzten Speicher, halbgeschriebene Dateien und dergleichen beschädigt haben.
Also, solltest du
join
oder verwendendetach
?join
detach
quelle
Sie sollten anrufen,
detach
wenn Sie nicht auf den Abschluss des Threads warten möchten,join
sondern der Thread stattdessen nur so lange ausgeführt wird, bis er fertig ist, und dann beenden, ohne dass der Haupt-Thread speziell darauf wartet.detach
Grundsätzlich werden die Ressourcen freigegeben, die für die Implementierung erforderlich sindjoin
.Es ist ein schwerwiegender Fehler , wenn ein Thread - Objekt sein Leben endet und weder
join
nochdetach
genannt wurde; in diesem Fallterminate
wird aufgerufen.quelle
Wenn Sie den Thread trennen, bedeutet dies, dass Sie dies nicht müssen
join()
ihn vor dem Beendenmain()
.Die Thread-Bibliothek wartet tatsächlich auf jeden solchen Thread unter main , aber Sie sollten sich nicht darum kümmern.
detach()
Dies ist vor allem dann nützlich, wenn Sie eine Aufgabe haben, die im Hintergrund ausgeführt werden muss, deren Ausführung Ihnen jedoch egal ist. Dies ist normalerweise bei einigen Bibliotheken der Fall. Möglicherweise erstellen sie stillschweigend einen Hintergrund-Worker-Thread und trennen ihn, sodass Sie ihn nicht einmal bemerken.quelle
Diese Antwort zielt darauf ab, die Frage im Titel zu beantworten, anstatt den Unterschied zwischen
join
und zu erklärendetach
. Also wann solltestd::thread::detach
sollte es verwendet werden?In ordnungsgemäß gepflegtem C ++
std::thread::detach
sollte Code überhaupt nicht verwendet werden. Der Programmierer muss sicherstellen, dass alle erstellten Threads ordnungsgemäß beendet werden, um alle erfassten Ressourcen freizugeben und andere erforderliche Bereinigungsaktionen auszuführen. Dies bedeutet, dass das Aufgeben des Eigentums an Threads durch Aufrufendetach
keine Option ist und daherjoin
in allen Szenarien verwendet werden sollte.Einige Anwendungen basieren jedoch auf alten und oft nicht gut gestalteten und unterstützten APIs, die möglicherweise unbegrenzt blockierende Funktionen enthalten. Das Verschieben von Aufrufen dieser Funktionen in einen dedizierten Thread, um das Blockieren anderer Inhalte zu vermeiden, ist eine gängige Praxis. Es gibt keine Möglichkeit, einen solchen Thread ordnungsgemäß zu beenden, sodass die Verwendung von
join
nur zum Blockieren des primären Threads führt. Dies ist eine Situation, in der die Verwendungdetach
eine weniger böse Alternative wäre, um beispielsweise einthread
Objekt mit dynamischer Speicherdauer zuzuweisen und es dann absichtlich zu verlieren.quelle
Laut cppreference.com :
Beispielsweise:
Beachten Sie die lokale Variable:
my_thread
Während die Lebensdauer von abgelaufenmy_thread
ist, wird der Destruktor vonstd::thread
aufgerufen undstd::terminate()
innerhalb des Destruktors aufgerufen.Aber wenn Sie verwenden
detach()
, sollten Sie nichtmy_thread
mehr verwenden, auch wenn die Lebensdauer von abgelaufenmy_thread
ist, wird dem neuen Thread nichts passieren.quelle
&
in der Lambda-Erfassung die Variablen des umschließenden Bereichs als Referenz verwenden. Stellen Sie daher besser sicher, dass die Lebensdauer Ihrer Referenz länger ist als Ihre Thread-Lebensdauer.