threads thread not libreria ejemplos ejemplo declared algorithms c++ multithreading c++11 stdthread

not - C++ 11: ¿Qué sucede si no llama a join() para std:: thread



thread was not declared in this scope (3)

Dada a continuación:

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 saldrá después de 5 segundos, ¿qué pasará con th1 que aún se está ejecutando?

¿Continúa ejecutándose hasta que se complete, incluso si el objeto th1 subproceso que th1 en main se sale del alcance y se destruye?

¿ th1 simplemente se th1 allí después de que se termina de ejecutar o de alguna manera se limpia cuando el programa termina?

¿Qué sucede si el subproceso se creó en una función, no en la main ? ¿Permanece el subproceso hasta que el programa termina o cuando la función queda fuera del alcance?

¿Es seguro simplemente no llamar a join a un subproceso si desea algún tipo de comportamiento de tiempo de espera en el subproceso?


En C ++ 11, debe especificar explícitamente "qué sucede" cuando el subproceso recién creado se sale del ámbito (se llama nuestro dtor). A veces, cuando estamos seguros de que el subproceso principal continúa y nuestros subprocesos están actuando como "canalizaciones", es seguro "separarlos (") de ellos; y, a veces, cuando estamos esperando que nuestros hilos de TRABAJADORES completen sus operaciones, nos unimos a ().

Como dice boost.org/doc/libs/1_57_0/doc/html/thread/… , el programador debe asegurarse de que el destructor nunca se ejecute mientras el hilo aún pueda unirse.

Especifique su estrategia multi-hilo. En este ejemplo, se llama a std::terminate() .


Si no ha desconectado o unido un subproceso cuando se llama al destructor, se llamará std::terminate , podemos ver esto al ir al borrador del estándar C ++ 11 , vemos que la sección 30.3.1.3 subprocesador dice:

Si se puede unir (), se llama a std :: terminate (). De lo contrario, no tiene efectos. [Nota: ya sea separar o unir implícitamente un subproceso joable () en su destructor podría resultar difícil corregir errores (para separar) o errores de rendimiento (para unir) solo cuando se produce una excepción. Por lo tanto, el programador debe asegurarse de que el destructor nunca se ejecute mientras el subproceso aún pueda unirse. "Nota final"

En cuanto a los fundamentos de este comportamiento, podemos encontrar un buen resumen en (No) usando std :: thread

¿Por qué el destructor de un hilo que se puede unir tiene que llamar a std :: terminate? Después de todo, el destructor podría unirse al subproceso secundario, o podría separarse del subproceso secundario, o podría cancelar el subproceso. En resumen, no puede unirse al destructor ya que esto podría provocar una congelación inesperada del programa (no se indica explícitamente en el código) en caso de que f2 se lance.

Y sigue un ejemplo y también dice:

No se puede separar, ya que arriesgaría la situación en la que el subproceso principal abandona el ámbito en el que se inició el subproceso secundario, y el subproceso secundario sigue ejecutándose y mantiene las referencias al alcance que ya no existe.

El artículo hace referencia a N2802: un motivo para reconsiderar la separación de la destrucción de los objetos de hilos que es un argumento en contra de la propuesta anterior, que fue separable de la destrucción si se puede juntar, y señala que una de las dos alternativas sería la de unirse, lo que podría llevar a puntos muertos. otra alternativa es lo que tenemos hoy en día, que es std::terminate en destrucción si se puede unir.


std::thread::~thread()

Si * esto tiene un hilo asociado ( joinable() == true ), se llama a std::terminate()

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

Esto significa que un programa como este no está bien formado ni es seguro.

Sin embargo, boost::thread::~thread() que boost::thread::~thread() llama a detach() en este caso. (como lo indicó dyp del usuario en los comentarios, este comportamiento está en desuso en versiones más recientes)

Siempre se puede solucionar esto utilizando RAII. Simplemente envuelva su hilo dentro de otra clase, que tendrá un comportamiento deseado en la destrucción.