Je n'ai pas besoin de terminer correctement le thread ou de le faire répondre à une commande "terminer". Je suis intéressé à terminer le thread avec force en utilisant du C ++ 11 pur.
Je n'ai pas besoin de terminer correctement le thread ou de le faire répondre à une commande "terminer". Je suis intéressé à terminer le thread avec force en utilisant du C ++ 11 pur.
Réponses:
Vous pouvez appeler à std::terminate()
partir de n'importe quel thread et le thread auquel vous faites référence se terminera de force.
Vous pouvez faire en sorte ~thread()
d'être exécuté sur l'objet du thread cible, sans intervention join()
ni detach()
sur cet objet. Cela aura le même effet que l'option 1.
Vous pouvez concevoir une exception qui a un destructeur qui lève une exception. Et puis faites en sorte que le thread cible lève cette exception lorsqu'il doit être arrêté de force. La partie délicate de celui-ci est d'amener le thread cible à lever cette exception.
Les options 1 et 2 ne fuient pas les ressources intra-processus, mais elles terminent chaque thread.
L'option 3 entraînera probablement une fuite de ressources, mais elle est partiellement coopérative en ce que le thread cible doit accepter de lever l'exception.
Il n'y a pas de moyen portable en C ++ 11 (à ma connaissance) de tuer de manière non coopérative un seul thread dans un programme multi-thread (c'est-à-dire sans tuer tous les threads). Il n'y avait aucune motivation pour concevoir une telle fonctionnalité.
A std::thread
peut avoir cette fonction membre:
native_handle_type native_handle();
Vous pourrez peut-être l'utiliser pour appeler une fonction dépendante du système d'exploitation pour faire ce que vous voulez. Par exemple sur les OS d'Apple, cette fonction existe et native_handle_type
est un pthread_t
. Si vous réussissez, vous risquez de perdre des ressources.
std::terminate
n'appelle ni les destructeurs statiques ni ne vide les tampons de sortie, donc l'ordre dans lequel les ressources sont libérées n'est pas bien défini, et vous n'avez aucune garantie que l'une de vos données est visible par l'utilisateur ou écrite dans le magasin permanent, ou même cohérent et complet.
exit()
ou abort()
au même effet global.
La réponse de @Howard Hinnant est à la fois correcte et complète. Mais il pourrait être mal compris s'il est lu trop rapidement, parce que std::terminate()
(tout le processus) a le même nom que le "terminateur" que @AlexanderVX avait en tête (1 thread).
Résumé: "terminer 1 thread + avec force (le thread cible ne coopère pas) + C ++ 11 pur = pas moyen."
std::terminate()
réponse est comme une histoire malicieuse classique de Djinn; il accomplit tout ce que souhaite le PO à la lettre, mais probablement pas de la manière qu'il voulait dire . L'humour discret m'a fait sourire. :-)
Cette question a en fait une nature plus profonde et une bonne compréhension des concepts multithreading en général vous donnera un aperçu de ce sujet. En fait, il n'y a pas de langage ni de système d'exploitation qui vous offrent des possibilités de terminaison de threads asynchrone brutalement sans avertissement de ne pas les utiliser. Et tous ces environnements d'exécution conseillent fortement les développeurs ou même nécessitent de créer des applications multithreading sur la base d'une terminaison de thread coopérative ou synchrone. La raison de ces décisions et conseils communs est qu'ils sont tous construits sur la base du même modèle multithreading général.
Comparons les concepts de multitraitement et de multithreading pour mieux comprendre les avantages et les limites du second.
Le multitraitement suppose la division de l'ensemble de l'environnement d'exécution en un ensemble de processus complètement isolés contrôlés par le système d'exploitation. Process incorpore et isole l'état de l'environnement d'exécution, y compris la mémoire locale du processus et les données qu'il contient, ainsi que toutes les ressources système telles que les fichiers, les sockets et les objets de synchronisation. L'isolement est une caractéristique extrêmement importante du processus, car elle limite la propagation des défauts par les frontières du processus. En d'autres termes, aucun processus ne peut affecter la cohérence d'un autre processus dans le système. Il en va de même pour le comportement du processus mais de manière moins restreinte et plus floue. Dans un tel environnement, n'importe quel processus peut être tué à n'importe quel moment "arbitraire", car premièrement chaque processus est isolé, deuxièmement
En revanche, le multithreading suppose l'exécution de plusieurs threads dans le même processus. Mais tous ces threads partagent la même boîte d'isolation et il n'y a aucun contrôle du système d'exploitation sur l'état interne du processus. En conséquence, n'importe quel thread est capable de modifier l'état global du processus et de le corrompre. Au même moment, les points dans lesquels l'état du thread est bien connu pour être sûr de tuer un thread dépendent complètement de la logique de l'application et ne sont connus ni pour le système d'exploitation ni pour l'exécution du langage de programmation. En conséquence, l'arrêt du thread à un moment arbitraire signifie le tuer à un point arbitraire de son chemin d'exécution et peut facilement conduire à la corruption des données, à la mémoire et aux fuites de traitement à l'échelle du processus,
Pour cette raison, l'approche courante consiste à forcer les développeurs à implémenter la terminaison de thread synchrone ou coopérative, où l'un des threads peut demander une autre terminaison de thread et l'autre thread dans un point bien défini peut vérifier cette demande et démarrer la procédure d'arrêt à partir de l'état bien défini. avec la libération de toutes les ressources à l'échelle du système mondial et des ressources locales à l'échelle du processus de manière sûre et cohérente.
Conseils d'utilisation de la fonction dépendante du système d'exploitation pour terminer le thread C ++:
std::thread::native_handle()
peut uniquement obtenir le type de handle natif valide du thread avant d'appeler join()
ou detach()
. Après cela, native_handle()
renvoie 0 - pthread_cancel()
coredump.
Pour appeler efficacement la fonction de terminaison de thread natif (par exemple pthread_cancel()
), vous devez enregistrer le handle natif avant d'appeler std::thread::join()
ou std::thread::detach()
. Pour que votre terminateur natif ait toujours un handle natif valide à utiliser.
Pour plus d'explications, veuillez consulter: http://bo-yang.github.io/2017/11/19/cpp-kill-detached-thread .
Je suppose que le fil qui doit être tué est soit dans n'importe quel mode d'attente, soit en effectuant un travail difficile. Je suggérerais d'utiliser une manière «naïve».
Définissez un booléen global:
std::atomic_bool stop_thread_1 = false;
Placez le code suivant (ou similaire) en plusieurs points clés, de manière à ce que toutes les fonctions de la pile d'appels soient renvoyées jusqu'à ce que le thread se termine naturellement:
if (stop_thread_1)
return;
Ensuite, pour arrêter le thread d'un autre thread (principal):
stop_thread_1 = true;
thread1.join ();
stop_thread_1 = false; //(for next time. this can be when starting the thread instead)