2008-09-16 9 views
20

Je suis en train de coder l'arrêt d'un serveur multithread.Si tout se passe comme prévu, tous les threads sortent par leurs propres moyens, mais il y a une petite chance qu'un thread se bloque. Dans ce cas, il serait pratique avoir une jointure non bloquante pour que je puisse le faire.Non bloquant pthread_join

Existe-t-il un moyen de faire un pthread_join non bloquant? Une sorte de jointure temporisée serait bien aussi.

quelque chose comme ceci:

 
foreach thread do 
    nb_pthread_join(); 
    if still running 
     pthread_cancel(); 

je peux penser plus de cas où une jointure non-bloking serait utile. Comme il semble qu'il n'y a pas une telle fonction, j'ai déjà codé une solution de contournement, mais ce n'est pas aussi simple que je le voudrais.

+1

jointure de fil non bloquante? Je pensais que rejoindre était tout au sujet de blocage: s –

Répondre

1

Comme d'autres l'ont souligné qu'il n'y a pas pthread_join non bloquante disponible dans les bibliothèques standard pthread.

Cependant, compte tenu de votre problème déclaré (en essayant de garantir que tous vos fils ont quitté à l'arrêt du programme) une telle fonction n'est pas nécessaire.Vous pouvez simplement faire ceci:

int killed_threads = 0; 
for(i = 0; i < num_threads; i++) { 
    int return = pthread_cancel(threads[i]); 
    if(return != ESRCH) 
     killed_threads++; 
} 
if(killed_threads) 
    printf("%d threads did not shutdown properly\n", killed_threads) 
else 
    printf("All threads exited successfully"); 

Il n'y a rien de mal à appeler pthread_cancel sur tous vos fils (terminé ou non) afin d'appeler que pour tous vos fils ne bloque pas et garantira la sortie de fil (propre ou non).

Cela devrait être considéré comme une solution de contournement «simple».

+22

Cette réponse est fausse. Le fait d'avoir appelé 'pthread_cancel' avec succès sur chaque thread ne garantit pas que tous les threads se sont terminés. Ils pourraient n'avoir atteint aucun point d'annulation, ou même s'ils l'ont fait, le thread principal pourrait être programmé en premier et revenir de 'main', tuant le processus, avant que les autres threads puissent finir de nettoyer ... –

0

Vous pouvez insérer un octet dans un tube ouvert comme non bloquant pour signaler à l'autre thread lorsque cela est fait, puis utiliser une lecture non bloquante pour vérifier l'état du tube.

1

La réponse dépend vraiment de la raison pour laquelle vous voulez faire cela. Si vous voulez simplement nettoyer les threads morts, par exemple, il est probablement plus simple d'avoir un thread "dead thread cleaner" qui boucle et se joint.

1

Je ne suis pas sûr de ce que vous voulez dire exactement, mais je suppose que ce que vous avez vraiment besoin est une attente et de notification mécanisme.

En bref, voici comment cela fonctionne: Vous attendez une condition pour satisfaire à un délai d'attente. Votre attente sera plus si:

  • Le délai d'attente se produit, ou
  • Si la condition est satisfaite.

Vous pouvez avoir ceci dans une boucle et ajouter un peu plus d'intelligence à votre logique. La meilleure ressource que j'ai trouvée pour cela concerne Pthreads est ce tutoriel: POSIX Threads Programming (https://computing.llnl.gov/tutorials/pthreads/).

Je suis très surpris de voir qu'il n'y a pas d'API pour rejoindre chronométré à Pthreads.

1

Il n'y a pas chronométré pthread_join, mais si vous êtes en attente d'autres thread bloqué sur les conditions, vous pouvez utiliser chronométré pthread_cond_timed_wait au lieu de pthread_cond_wait

2

Si vous développez pour QNX, vous pouvez utiliser la fonction pthread_timedjoin().

Sinon, vous pouvez créer un thread séparé qui exécutera pthread_join() et alerter le thread parent, en signalant par exemple un sémaphore, que le thread enfant est terminé. Ce thread séparé peut retourner ce qui est obtenu de pthread_join() pour laisser le thread parent déterminer non seulement quand l'enfant termine mais aussi quelle valeur il retourne.

21

Si vous exécutez votre application sur Linux, vous pouvez être intéressé de savoir que:

int pthread_tryjoin_np(pthread_t thread, void **retval); 

int pthread_timedjoin_np(pthread_t thread, void **retval, 
           const struct timespec *abstime); 

Soyez prudent, car le suffixe l'indique, "np" signifie "non-portable". Ils ne sont pas standard POSIX, les extensions GNU, utiles cependant.

link to man page

9

Le mécanisme de « pthread_join » est pratique d'utiliser si elle arrive à faire exactement ce que vous voulez. Il ne fait rien que vous ne pourriez pas faire vous-même, et où ce n'est pas exactement ce que vous voulez, codez exactement ce que vous voulez.

Il n'y a pas vraiment de raison que vous vous souciez réellement de la fin ou non d'un thread. Ce qui vous intéresse, c'est de savoir si le travail que le thread faisait était terminé. Pour le dire, demandez au thread de faire quelque chose pour indiquer qu'il fonctionne. Comment vous faites cela dépend de ce qui est idéal pour votre problème spécifique, qui dépend fortement de ce que les threads font.

Commencez par changer d'avis. Ce n'est pas un fil qui se coince, c'est ce que le thread faisait qui est bloqué.

+0

J'ai à peu près le même problème, un processus appelle deux threads et ne devrait sortir qu'à la sortie des threads - aucune des réponses ici n'a expliqué comment faire quelque chose de similaire à la fonction wait() de fork. (J'ai ajouté cette question aux favoris, elle m'avertira une fois que vous répondrez automatiquement) –

+2

Avoir un booléen, protégé par un mutex, qui stocke le statut de la chose que vous voulez savoir. Si vous le souhaitez, utilisez une variable de condition pour vous signaler le changement du booléen. –

+0

Merci. Un exemple de code serait utile, mais je pourrais aussi essayer de chercher ailleurs. –

Questions connexes