J'ai le fil qui dort pendant une longue période, puis se réveille pour faire quelque chose, puis dormir à nouveau, comme ceci: Comment puis-je sortir de ce fil gracieusement et rapidement? < / p> J'ai essayé d'utiliser Alors, y a-t-il de bonnes idées? P> p> pthread_cancel () code>, mais les fils de couchage n'ont pas pu être annulés.
J'ai également essayé de changer l'état de la boucle tandis que la boucle, mais cela va toujours prendre longtemps à la sortie.
Et je ne veux pas utiliser
pthread_kill () code>, car il peut tuer le fil quand il fonctionne. P>
3 Réponses :
comme alternative à Ceci est similaire à la manière dont vous pourriez le faire en C # / Java à l'aide d'attendre et de notifier. P> dormir code>, vous pouvez utiliser pthread_cond_timedwait avec un temporisateur de 1000 ms. Ensuite, lorsque vous souhaitez quitter, signalez la variable de condition. P>
Correct. C'est le moyen simple et non racé de le faire.
Ceci est correct, mais l'annulation est plus facile et peut-être légèrement plus efficace. Bien sûr, si vous appelez pthread_cancel code> sur le thread, vous devez vous assurer qu'il ne peut pas être annulé à un moment de cela. Appelant
pthread_setcancelstate code> Pour désactiver l'annulation Lorsque le thread démarre, et ne le permettant que juste avant la veille code> code>, serait une approche sécurisée.
Imo, pthread_cancel () code> peut être préférable car
Sleep () code> est déjà un point d'annulation. Et assurez-vous d'appeler
pthread_cleanup_push () code> et
pthread_cleanup_pop () code> Pour configurer les gestionnaires de nettoyage si vous avez alloué des ressources.
Quelle est la différence entre utiliser pthread_cond_timpedwait code> avec un délai d'attente de 1000 ms et utiliser une variable de drapeau avec 100 ms de sommeil en ce qui concerne la condition de course?
La variable classique Unix condition est le auto-pipe .
int fds[2]; pipe2(fds, O_NONBLOCK); // requires newish kernel and glibc; use pipe + 2*fcntl otherwise child: while (some_condition) { // do something struct pollfd pd = { .fd = fds[0], .events = POLLIN }; int rc; char c; while ((rc = poll(&pd, 1, 1000000)) == -1 && errno == EINTR) // not entirely correct; 1000000 should be decreased according to elapsed time when repeating after a signal interruption ; if (rc > 0 && (pd.revents & POLLIN) && read(fds[0], &c, 1) >= 0) break; } parent: cancel() { char c = 0; write(fds[1], &c, 1); }
Avez-vous utilisé pthread_cleanup_push et pop? L'annulation avec pthread_cancel ne fonctionne pas sans eux. Vous devez les utiliser par paires comme je l'ai fait dans l'exemple ci-dessous. Si vous oubliez un, il ne compilera pas (macros fantaisie, on a le '{' et l'autre a le '}'). Vous pouvez même nier différents niveaux de nettoyage / pop. Quoi qu'il en soit, ils définissent un long point de saut qui annule des sauts lors de l'annulation survient (assez cool). De plus, si votre programme de test n'attend pas que le thread commence ou s'arrête, vous ne remarquez peut-être pas l'annulation de l'annulation.
Exemple: P>
MAIN: waiting for thread to startup... THREAD: Enter Sleep MAIN: sending cancel... MAIN: waiting for thread to exit... THREAD: unwind (all threads, canceled or normal exit get here) MAIN: done
Vous pouvez utiliser pthread_cancel code> juste bien sans les gestionnaires de nettoyage, mais si vous avez alloué des ressources qui devraient être libérées, cela entraînerait une fuite de ressources.
Je suis sûr que vous avez raison quand il s'agit de ce sujet. J'avais déjà cru que CleanUp_Push et Pop configurent le Longjump que Pthread_Cancel a invoqué. Je suppose que vous dites que vous dites qu'il y a une configuration par défaut par pthread_create. Est-ce que je le fais bien?
À la fin de la chaîne des gestionnaires de nettoyage, le code de sortie du fil interne de mise en œuvre (qui inclut des destructeurs de données spécifiques à thread et éventuellement d'autres éléments spécifiques à la mise en œuvre). S'il n'y a pas de gestionnaires de nettoyage, l'exécution passe directement là-bas. L'annulation et un appel à pthread_exit code> par le fil lui-même ont cet effet.
Eh bien, je pense que je fais une erreur, dormir () est un point d'annulation défini par POSIX.1
Juste une note -
pthread_kill code> ne tue pas un fil. Il envoie un signal à un fil. Si l'action de ce signal doit résilier le processus (par exemple, l'action par défaut de
sigterm code> ou l'action non bloquée de
sigkill code>), il terminera tout le processus I>, pas le fil cible. Vraiment la seule fois
pthread_kill code> est utile, c'est si vous avez installé un gestionnaire de signal d'interruption et que vous souhaitez interrompre un système SYSCALL qui est bloqué dans un thread particulier (qui serait une solution potentielle à votre question).
Pourquoi avez-vous dit que le fil ne pouvait pas quitter rapidement? J'ai essayé cela et le fil annulé immédiatement sur
thread_cancel code>. Et j'ai pu
pthread_join code> sans délai.