En algún momento tengo que usar std::thread
para 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
}
std
yboost
las discusiones handetach
yjoin
modelada de cerca después de los hilos POSIX.Respuestas:
En el destructor de
std::thread
,std::terminate
se llama si:t.join()
)t.detach()
)Por lo tanto, siempre debe
join
odetach
un hilo antes de que los flujos de ejecución lleguen al destructor.Cuando un programa finaliza (es decir,
main
regresa), 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
join
odetach
?join
detach
fuente
Debe llamar
detach
si no va a esperar a que se completejoin
el subproceso, pero el subproceso seguirá funcionando hasta que esté hecho y luego terminará sin que el subproceso principal lo espere específicamente.detach
básicamente liberará los recursos necesarios para poder implementarjoin
.Es un error fatal si un objeto hilo termina su vida y ni
join
tampocodetach
se ha llamado; En este casoterminate
se 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
join
ydetach
. Entonces, ¿cuándo deberíastd::thread::detach
usarse?En el código C ++ mantenido correctamente
std::thread::detach
no 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 invocandodetach
no es una opción y, porjoin
lo 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
join
este solo conducirá al bloqueo del hilo primario. Esa es una situación en la que usardetach
sería una alternativa menos malvada para, por ejemplo, asignarthread
objetos 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_thread
mientrasmy_thread
finaliza la vida útil de ,std::thread
se 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_thread
ha 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.