En algún momento tengo que usar std::threadpara acelerar mi aplicación. También sé que join()espera hasta que se complete un hilo. Esto es fácil de entender, pero ¿cuál es la diferencia entre llamar detach()y no llamar?
Pensé que sin detach(), el método del hilo funcionará usando un hilo de forma independiente.
No se separa:
void Someclass::Somefunction() {
//...
std::thread t([ ] {
printf("thread called without detach");
});
//some code here
}
Llamando con desprendimiento:
void Someclass::Somefunction() {
//...
std::thread t([ ] {
printf("thread called with detach");
});
t.detach();
//some code here
}

stdyboostlas discusiones handetachyjoinmodelada de cerca después de los hilos POSIX.Respuestas:
En el destructor de
std::thread,std::terminatese llama si:t.join())t.detach())Por lo tanto, siempre debe
joinodetachun hilo antes de que los flujos de ejecución lleguen al destructor.Cuando un programa finaliza (es decir,
mainregresa), no se esperan los subprocesos separados que se ejecutan en segundo plano; en cambio, su ejecución se suspende y sus objetos locales de subprocesos se destruyen.Crucialmente, esto significa que la pila de esos hilos no se desenrolla y, por lo tanto, algunos destructores no se ejecutan. Dependiendo de las acciones que se suponía que debían emprender esos destructores, esta podría ser una situación tan grave como si el programa se hubiera bloqueado o hubiera sido asesinado. Esperemos que el sistema operativo libere los bloqueos en los archivos, etc. pero podría haber corrompido la memoria compartida, los archivos a medio escribir y similares.
Entonces, ¿deberías usar
joinodetach?joindetachfuente
Debe llamar
detachsi no va a esperar a que se completejoinel subproceso, pero el subproceso seguirá funcionando hasta que esté hecho y luego terminará sin que el subproceso principal lo espere específicamente.detachbásicamente liberará los recursos necesarios para poder implementarjoin.Es un error fatal si un objeto hilo termina su vida y ni
jointampocodetachse ha llamado; En este casoterminatese invoca.fuente
Cuando desconecta el hilo, significa que no tiene que
join()hacerlo antes de salirmain().La biblioteca de subprocesos realmente esperará cada uno de estos subprocesos debajo de main , pero no debería importarle.
detach()es principalmente útil cuando tiene una tarea que debe hacerse en segundo plano, pero no le importa su ejecución. Este suele ser un caso para algunas bibliotecas. Pueden crear silenciosamente un subproceso de trabajo en segundo plano y separarlo para que ni siquiera lo note.fuente
Esta respuesta tiene como objetivo responder la pregunta en el título, en lugar de explicar la diferencia entre
joinydetach. Entonces, ¿cuándo deberíastd::thread::detachusarse?En el código C ++ mantenido correctamente
std::thread::detachno se debe utilizar en absoluto. El programador debe asegurarse de que todos los hilos creados salgan con gracia liberando todos los recursos adquiridos y realizando otras acciones de limpieza necesarias. Esto implica que renunciar a la propiedad de los hilos invocandodetachno es una opción y, porjoinlo tanto, debe usarse en todos los escenarios.Sin embargo, algunas aplicaciones se basan en API antiguas, a menudo mal diseñadas y compatibles, que pueden contener funciones de bloqueo indefinido. Mover invocaciones de estas funciones a un hilo dedicado para evitar bloquear otras cosas es una práctica común. No hay forma de hacer que un hilo de este tipo salga con gracia, por lo que el uso de
joineste solo conducirá al bloqueo del hilo primario. Esa es una situación en la que usardetachsería una alternativa menos malvada para, por ejemplo, asignarthreadobjetos con una duración de almacenamiento dinámico y luego filtrarlos a propósito.fuente
De acuerdo con cppreference.com :
Por ejemplo:
Observe la variable local:
my_threadmientrasmy_threadfinaliza la vida útil de ,std::threadse llamará al destructor de ystd::terminate()se llamará dentro del destructor.Pero si lo usa
detach(), ya no debería usarlomy_thread, incluso si la vida útil demy_threadha terminado, no le pasará nada al nuevo hilo.fuente
&en la captura lambda está utilizando las variables del ámbito de inclusión por referencia , por lo que es mejor asegurarse de que la vida útil de cualquiera de las referencias sea más larga que la vida útil de su hilo.