No necesito terminar el hilo correctamente, o hacer que responda a un comando "terminar". Estoy interesado en terminar el hilo con fuerza usando C ++ 11 puro.
No necesito terminar el hilo correctamente, o hacer que responda a un comando "terminar". Estoy interesado en terminar el hilo con fuerza usando C ++ 11 puro.
Respuestas:
Puede llamar std::terminate()
desde cualquier hilo y el hilo al que se refiere terminará forzosamente.
Puede hacer arreglos para ~thread()
que se ejecute en el objeto del hilo objetivo, sin una intervención join()
ni detach()
en ese objeto. Esto tendrá el mismo efecto que la opción 1.
Podría diseñar una excepción que tenga un destructor que arroje una excepción. Y luego haga arreglos para que el hilo objetivo arroje esta excepción cuando se va a terminar con fuerza. La parte difícil de este es conseguir que el hilo objetivo arroje esta excepción.
Las opciones 1 y 2 no pierden recursos dentro del proceso, pero terminan cada hilo.
La opción 3 probablemente perderá recursos, pero es parcialmente cooperativa en que el hilo objetivo debe aceptar lanzar la excepción.
No hay una forma portátil en C ++ 11 (que yo sepa) de matar de forma no cooperativa un solo hilo en un programa de múltiples hilos (es decir, sin matar todos los hilos). No hubo motivación para diseñar tal característica.
A std::thread
puede tener esta función miembro:
native_handle_type native_handle();
Es posible que pueda usar esto para llamar a una función dependiente del sistema operativo para hacer lo que desee. Por ejemplo, en los sistemas operativos de Apple, esta función existe y native_handle_type
es a pthread_t
. Si tiene éxito, es probable que pierda recursos.
std::terminate
ni llama a los destructores estáticos ni vacía los búferes de salida, por lo que el orden en que se liberan los recursos no está bien definido, ni tiene ninguna garantía de que alguno de sus datos sea visible para el usuario o escrito en la tienda permanente, o incluso consistente y completo.
exit()
o abort()
al mismo efecto general.
La respuesta de @Howard Hinnant es correcta y completa. Pero podría malinterpretarse si se lee demasiado rápido, porque std::terminate()
(todo el proceso) tiene el mismo nombre que la "terminación" que @AlexanderVX tenía en mente (1 hilo).
Resumen: "terminar 1 hilo + con fuerza (el hilo objetivo no coopera) + puro C ++ 11 = De ninguna manera".
std::terminate()
respuesta es como una clásica historia traviesa de Djinn; cumple con todo lo que el OP desea al pie de la letra, aunque probablemente no de la manera que él quiso decir . El humor discreto me hizo sonreír. :-)
Esta pregunta en realidad tiene una naturaleza más profunda y una buena comprensión de los conceptos de subprocesos múltiples en general le proporcionará información sobre este tema. De hecho, no hay ningún idioma o sistema operativo que le brinde facilidades para la terminación asincrónica de subprocesos bruscamente sin advertencia de no usarlos. Y todos estos entornos de ejecución aconsejan encarecidamente al desarrollador o incluso requieren construir aplicaciones de subprocesos múltiples sobre la base de terminación de subprocesos cooperativa o síncrona. La razón de estas decisiones y consejos comunes es que todos se basan en el mismo modelo general de subprocesos múltiples.
Comparemos los conceptos de multiprocesamiento y subprocesamiento múltiple para comprender mejor las ventajas y limitaciones del segundo.
El multiprocesamiento supone la división de todo el entorno de ejecución en un conjunto de procesos completamente aislados controlados por el sistema operativo. El proceso incorpora y aísla el estado del entorno de ejecución, incluida la memoria local del proceso y los datos dentro de él y todos los recursos del sistema como archivos, sockets, objetos de sincronización. El aislamiento es una característica críticamente importante del proceso, ya que limita la propagación de fallas por las fronteras del proceso. En otras palabras, ningún proceso puede afectar la consistencia de cualquier otro proceso en el sistema. Lo mismo es cierto para el comportamiento del proceso, pero en la forma menos restringida y más borrosa. En dicho entorno, cualquier proceso puede ser eliminado en cualquier momento "arbitrario", porque en primer lugar cada proceso está aislado, en segundo lugar,
En contraste, el subproceso múltiple supone ejecutar múltiples subprocesos en el mismo proceso. Pero todos estos hilos comparten el mismo cuadro de aislamiento y no hay ningún control del sistema operativo sobre el estado interno del proceso. Como resultado, cualquier hilo puede cambiar el estado del proceso global, así como corromperlo. Al mismo tiempo, los puntos en los que se sabe que el estado del subproceso es seguro para matar un subproceso depende completamente de la lógica de la aplicación y no se conocen ni para el sistema operativo ni para el tiempo de ejecución del lenguaje de programación. Como resultado, la terminación de subprocesos en el momento arbitrario significa matarlo en el punto arbitrario de su ruta de ejecución y puede conducir fácilmente a la corrupción de datos, memoria y manejos de todo el proceso,
Debido a esto, el enfoque común es obligar a los desarrolladores a implementar la terminación de subprocesos sincrónica o cooperativa, donde un subproceso puede solicitar otra terminación de subprocesos y otro subproceso en un punto bien definido puede verificar esta solicitud e iniciar el procedimiento de apagado desde el estado bien definido con la liberación de todos los recursos globales de todo el sistema y los recursos locales de todo el proceso de manera segura y consistente.
Consejos para usar la función dependiente del sistema operativo para terminar el hilo de C ++:
std::thread::native_handle()
solo puede obtener el tipo de identificador nativo válido del hilo antes de llamar join()
o detach()
. Después de eso, native_handle()
devuelve 0 - se pthread_cancel()
reducirá.
Para llamar efectivamente a la función de terminación de subprocesos nativos (por ejemplo pthread_cancel()
), debe guardar el identificador nativo antes de llamar std::thread::join()
o std::thread::detach()
. Para que su terminador nativo siempre tenga un identificador nativo válido para usar.
Más explicaciones, consulte: http://bo-yang.github.io/2017/11/19/cpp-kill-detached-thread .
Supongo que el hilo que necesita ser eliminado está en cualquier tipo de modo de espera o está haciendo un trabajo pesado. Sugeriría usar una forma "ingenua".
Definir algunos booleanos globales:
std::atomic_bool stop_thread_1 = false;
Ponga el siguiente código (o similar) en varios puntos clave, de manera que haga que todas las funciones en la pila de llamadas regresen hasta que el hilo termine naturalmente:
if (stop_thread_1)
return;
Luego, para detener el hilo de otro hilo (principal):
stop_thread_1 = true;
thread1.join ();
stop_thread_1 = false; //(for next time. this can be when starting the thread instead)