Wozu Threads detachen?
-
Huhu,
Ich habe mich schon seit längerem gefragt, warum man Threads detachen sollen wollte. Schließlich gibt es keine Garantie, dass der Thread jemals in einer bestimmten Zeit fertig wird. Ich hätte verstanden, wenn am Ende der main auf detachte Threads gewartet wird, aber das ist offensichtlich nicht der Fall: http://ideone.com/NRvvV
Wozu ist das also gut?
Grüße,
Der Kellerautomat
-
Falls du andere Synchronisierungsmöglichkeiten als thread.join() verwenden möchtest.
Z. B. der Ersatz für das fehlende
async()in Boost:#include <boost/thread.hpp> #include <boost/utility/result_of.hpp> template <class F> boost::detail::thread_move_t<boost::unique_future<typename boost::result_of<F()>::type> > async(F f) { typedef typename boost::result_of<F()>::type R; boost::packaged_task<R> pt( f ); typedef boost::unique_future<R> future; future ret = pt.get_future(); boost::thread( boost::move(pt) ).detach(); return boost::move(ret); }
-
Das ist vom Konzept her ja auch nichts anderes als ein join, nur eben schöner verpackt.
-
@Bloobs: Ich verstehe das leider nicht. Was hat das async mit dem join zu tun. In Deinem Beispiel kann der thread doch noch ewig laufen. Ein ret.get() bedeutet ja nicht, dass der thread beendet wurde. Oder habe ich da was übersehen?
-
Kellerautomat schrieb:
Das ist vom Konzept her ja auch nichts anderes als ein join, nur eben schöner verpackt.
Es ist kein join() - deshalb ist detachen notwendig.
Manchmal interessiert der Thread aber auch nicht weiter - man feuert ihn ab und vergisst ihn.
Manchmal mag man auch andere synchronisations Tools verwenden um die Threads zu synchronisieren. uU ist der Thread nicht mehr Teil des Erstellers sondern woanders anzusiedeln.
Eine gewisse Art von join wird man meistens (aber nicht immer) dennoch verwenden. Nur muss es eben nicht zwangsläufig join() sein.
Was genau ist eigentlich deine Frage?
-
IMO entsteht durch das detachen automatisch implementation-defined bzw undefined behavior. Man weiß nicht, ob der Thread überhaupt zu Ende laufen wird, wenn nicht, wo er sich dann befindet. Das kann doch nur schief gehen?
-
Kellerautomat schrieb:
IMO entsteht durch das detachen automatisch implementation-defined bzw undefined behavior.
Nein, wieso?
Ich könnte statt join() ja WaitForSingleObject() verwenden. Perfekt definiert was passiert. Nur weil man detached heisst es ja nicht, dass man den Thread in den Wind schiesst. Es heisst lediglich, dass man diese 2 Threads nicht verknüpft haben will. uU läuft der gespawnte Thread einfach länger als der Threadstarter...
Deshalb nochmal: was genau ist deine Frage?
join() ist nur eine Funktion. Du tust so als würde es nichts anderes geben. Ich kann ein C++ Programm auch komplett ohne iostreams schreiben und dennoch Text auf dem Bildschirm ausgeben...
-
detach heißt doch, dass das Thread-Handle ungültig wird und es keine Möglichkeit mehr gibt, außerhalb des Threads auf denselben zuzugreifen. Der detachte Thread läuft unabhängig vom Rest.
Das heißt aber auch, dass ich nicht mehr auf ihn warten kann. Wenn der Main-Thread beendet wird, wird der detachte Thread im Zuge der Prozessaufräumarbeiten terminiert, was in etwa UB entspricht.
-
Kellerautomat schrieb:
detach heißt doch, dass das Thread-Handle ungültig wird und es keine Möglichkeit mehr gibt, außerhalb des Threads auf denselben zuzugreifen.
Nein, das heisst es nicht.
Wieso sollte es das heissen? Nur weil das eine Handle das du hast ungültig wird, heisst es nicht dass du keine Möglichkeit der Kommunikation mehr hast. Du versteifst dich zu sehr auf eine API Funktion.
Ich brauche kein Handle zu dem anderen Thread um ihn synchronisieren zu können. Ich kann per Mutex synchronisieren oder aber auch das Handle aus dem erzeugten Thread heraus weiter geben.
Stell dir folgendes vor. Du hast eine Server der Anfragen entgegen nimmt. Diese Entgegennehmlogig erstellt immer nur einen Thread mit den Verbindungsdaten und vergisst ihn gleich wieder und wartet auf die nächste Anfrage.
Der Thread registriert sich bei einem Thread-Manager, macht seine Arbeit, und beim beenden löscht er sich aus dem Thread Manager. Der Thread Manager macht garnichts, ausser beobachten wieviele Threads offen sind und aufpassen dass das Programm nicht beendet wird solange noch Threads offfen sind.
Du hast nirgendwo ein join() - wozu auch?
Vergiss die API und denkt an das "Big Picture". Ein Thread ist eine komplette Einheit. Er muss nicht einem anderen Thread gehören. Schau dir mal andere APIs an zB die WinAPI - da gibt es meistens kein join().
PS:
vergleiche das mit Smartpointer.
wenn du shared_ptr<Foo> p(new Foo()); machst, verlierst du ja auch das handle auf new Foo() (wenn wir mal von p.get() absehen). Und dennoch ist da kein UB, weil der shared_ptr sich selber super verwalten kann.
-
Shade Of Mine schrieb:
Schau dir mal andere APIs an zB die WinAPI - da gibt es meistens kein join().
Doch klar gibts alles, heisst bloss ein wenig anders.
-
hustbaer schrieb:
Shade Of Mine schrieb:
Schau dir mal andere APIs an zB die WinAPI - da gibt es meistens kein join().
Doch klar gibts alles, heisst bloss ein wenig anders.
Shade hats ja sogar selbst schon erwähnt...
