it-swarm.com.de

Wann sollte pthread_exit () und wann pthread_join () in Linux verwendet werden?

Ich bin neu bei Pthreads und versuche es zu verstehen. Ich habe einige Beispiele wie die folgenden gesehen. 

Ich konnte sehen, dass main() von der API pthread_exit() blockiert wird, und ich habe Beispiele gesehen, bei denen die Hauptfunktion von der API pthread_join() blockiert wird. Ich kann nicht verstehen, wann ich was benutzen soll? 

Ich beziehe mich auf die folgende Site - https://computing.llnl.gov/tutorials/pthreads/ . Ich kann nicht verstehen, wann pthread_join() und pthread_exit() verwendet werden soll. 

Kann jemand bitte erklären? Ein guter Tutorial-Link für Pthreads wird ebenfalls geschätzt.

#include <pthread.h>
#include <stdio.h>
#define NUM_THREADS     5

void *PrintHello(void *threadid)
{
   long tid;
   tid = (long)threadid;
   printf("Hello World! It's me, thread #%ld!\n", tid);
   pthread_exit(NULL);
}

int main (int argc, char *argv[])
{
   pthread_t threads[NUM_THREADS];
   int rc;
   long t;
   for(t=0; t<NUM_THREADS; t++){
      printf("In main: creating thread %ld\n", t);
      rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
      if (rc){
         printf("ERROR; return code from pthread_create() is %d\n", rc);
         exit(-1);
      }
   }

   /* Last thing that main() should do */
   pthread_exit(NULL);

Eine weitere Sache realisiert, d.h. 

pthread_cancel(thread);
pthread_join(thread, NULL);

Manchmal möchten Sie den Thread abbrechen, während er ausgeführt wird . Sie können dies mit pthread_cancel (thread); ..__ tun. Denken Sie jedoch daran, dass Sie die Unterstützung für pthread cancel aktivieren müssen ..__ Code bei Stornierung.

thread_cleanup_Push(my_thread_cleanup_handler, resources);
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, 0);

static void my_thread_cleanup_handler(void *arg)
{
  // free
  // close, fclose
}
39

Wie in den openpub-Dokumentationen erläutert,

pthread_exit() beendet den Thread, der ihn aufruft. 

In Ihrem Fall wird main thread beendet, während Ihre generierten Threads die Ausführung fortsetzen. Dies wird meistens in Fällen verwendet, in denen der Haupt-Thread nur zum Erzeugen von Threads benötigt wird und die Threads ihre Arbeit erledigen lassen

pthread_join setzt die Ausführung des Threads, der ihn aufgerufen hat, aus, es sei denn, der Ziel-Thread wird beendet

Dies ist nützlich, wenn Sie warten möchten, dass der Thread/die Threads beendet werden, bevor die Weiterverarbeitung im Hauptthread fortgesetzt wird.

39

pthread_exit beendet den aufrufenden Thread, während pthread_join die Ausführung des aufrufenden Threads anhält, bis die Ausführung des Ziel-Threads abgeschlossen ist. 

Sie sind in der offenen Gruppendokumentation ziemlich gut erklärt: 

13
Alok Save

Beide Methoden stellen sicher, dass Ihr Prozess nicht endet, bevor alle Threads beendet sind.

Bei der Join-Methode wartet Ihr Thread der main-Funktion explizit auf alle Threads, die "verbunden" werden sollen.

Die pthread_exit-Methode beendet Ihre main-Funktion und Ihren Thread kontrolliert. main hat die Besonderheit, dass die Endung main Ihren gesamten Prozess einschließlich aller anderen Threads beenden würde.

Damit dies funktioniert, müssen Sie sicherstellen, dass keiner Ihrer Threads lokale Variablen verwendet, die in der main-Funktion deklariert sind. Der Vorteil dieser Methode ist, dass Ihre main nicht alle Threads kennen muss, die in Ihrem Prozess gestartet wurden, z. B. weil andere Threads selbst neue Threads erstellt haben, über die main nichts weiß.

8
Jens Gustedt

Die pthread_exit () - API

wird, wie bereits erwähnt, für die aufrufende Thread-Beendigung verwendet .. Nach einem Aufruf dieser Funktion wird ein komplizierender Bereinigungsmechanismus gestartet. Wenn der Thread beendet ist, wird der Thread beendet. Die API pthread_exit () wird auch implizit aufgerufen, wenn ein Aufruf der return () - Routine in einem von pthread_create () .. erstellten Thread auftritt. Tatsächlich haben ein Aufruf von return () und ein Aufruf von pthread_exit () dieselbe Wirkung, wenn sie von a aufgerufen werden Thread erstellt von pthread_create ().

Es ist sehr wichtig, den ursprünglichen Thread zu unterscheiden, der implizit erstellt wird, wenn die main () - Funktion gestartet wird, und Threads, die von pthread_create () ..__ erstellt werden. Ein Aufruf der Routine return () von der main () - Funktion ruft implizit den exit ( ) Systemaufruf und der gesamte Prozess wird beendet . Es wird kein Thread-Bereinigungsmechanismus gestartet . Ein Aufruf der Funktion pthread_exit () von der Funktion main () führt dazu, dass der Bereinigungsmechanismus startet, und wenn er seine Arbeit beendet hat anfänglicher Thread beendet.

Was mit dem gesamten Prozess (und mit anderen Threads) geschieht, wenn pthread_exit () von der Funktion main () aufgerufen wird, hängt von der PTHREAD-Implementierung ab .. __ Bei der IBM OS/400-Implementierung wird beispielsweise der gesamte Prozess einschließlich anderer beendet Threads, wenn pthread_exit () von der main () - Funktion aufgerufen wird . Andere Systeme verhalten sich möglicherweise anders ..__ Auf den meisten modernen Linux-Computern beendet ein Aufruf von pthread_exit () aus dem ursprünglichen Thread den gesamten Prozess erst dann, wenn alles abgeschlossen ist Thread-Beendigung . Seien Sie vorsichtig mit pthread_exit () von main (), wenn Sie eine portable Anwendung schreiben möchten.

Die pthread_join () - API

ist eine bequeme Methode, um auf eine Thread-Beendigung zu warten ..__ Sie können eine eigene Funktion schreiben, die auf eine Thread-Beendigung wartet, die möglicherweise besser für Ihre Anwendung geeignet ist, anstatt pthread_join () ..__ zu verwenden. Dies kann beispielsweise der Fall sein eine Funktion, die auf dem Warten auf bedingte Variablen basiert.

Ich würde empfehlen, ein Buch von David R. Butenhof „Programmierung mit POSIX-Threads“ zu lesen. Es erklärt die besprochenen Themen (und kompliziertere Dinge) sehr gut (obwohl einige Implementierungsdetails, wie die Verwendung von pthread_exit in der Hauptfunktion, nicht immer im Buch wiedergegeben werden). 

2
MichaelGoren

Sie brauchen keine Anrufe an pthread_exit(3) in Ihrem speziellen Code.

Im Allgemeinen sollte der Thread mainnotpthread_exit aufrufen, er sollte jedoch häufig pthread_join(3) to wait aufrufen, damit ein anderer Thread beendet wird.

In Ihrer PrintHello-Funktion müssen Sie pthread_exit nicht aufrufen, da dies nach der Rückkehr von dieser implizit ist.

Ihr Code sollte also eher lauten:

void *PrintHello(void *threadid)  {
  long tid = (long)threadid;
  printf("Hello World! It's me, thread #%ld!\n", tid);
  return threadid;
}

int main (int argc, char *argv[]) {
   pthread_t threads[NUM_THREADS];
   int rc;
   intptr_t t;
   // create all the threads
   for(t=0; t<NUM_THREADS; t++){
     printf("In main: creating thread %ld\n", (long) t);
     rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
     if (rc) { fprintf(stderr, "failed to create thread #%ld - %s\n",
                                (long)t, strerror(rc));
               exit(EXIT_FAILURE);
             };
   }
   pthread_yield(); // useful to give other threads more chance to run
   // join all the threads
   for(t=0; t<NUM_THREADS; t++){
      printf("In main: joining thread #%ld\n", (long) t);
      rc = pthread_join(&threads[t], NULL);
      if (rc) { fprintf(stderr, "failed to join thread #%ld - %s\n",
                                (long)t, strerror(rc));
               exit(EXIT_FAILURE);
      }
   }
}

pthread_exit() beendet den aufrufenden Thread und beendet diesen (die vom aufrufenden Thread verwendeten Ressourcen werden jedoch nicht an das Betriebssystem freigegeben, wenn sie nicht vom Haupt-Thread getrennt werden.)

pthrade_join() wartet oder blockiert den aufrufenden Thread, bis der Ziel-Thread nicht beendet ist ..__ In einfachen Word wird darauf gewartet, dass der Ziel-Thread beendet wird.

Wenn Sie in Ihrem Code vor pthread_exit() in die Funktion PrintHello den Ruhezustand (oder die Verzögerung) eingeben, wird der Haupt-Thread möglicherweise beendet und beendet den vollständigen Prozess. Obwohl die Funktion PrintHello nicht abgeschlossen ist, wird sie beendet. Wenn Sie die Funktion pthrade_join() in main verwenden, bevor Sie pthread_exit() von main aus aufrufen, wird der Haupt-Thread blockiert und der Aufruf des aufrufenden Threads (PrintHello) abgewartet. 

2
Abhitesh khatri

Hmm.

POSIX pthread_exit Beschreibung aus http://pubs.opengroup.org/onlinepubs/009604599/functions/pthread_exit.html :

After a thread has terminated, the result of access to local (auto) variables of the thread is 
undefined. Thus, references to local variables of the exiting thread should not be used for 
the pthread_exit() value_ptr parameter value.

Dies scheint der Idee zu widersprechen, dass lokale main () - Threadvariablen zugänglich bleiben.

1
jim mcnamara

Wenn Sie pthread_exit im Haupt-Thread (anstelle von pthread_join) verwenden, bleibt der Haupt-Thread im Status "nicht funktionsfähig" (Zombie). Da pthread_join nicht verwendet wird, bleiben auch andere verknüpfte Threads, die beendet werden, im Zombie-Status und verursachen resource leakage .

Ein Fehler beim Join mit einem Thread, der verbunden werden kann (d. H. Ein Nicht getrennt), führt zu einem "Zombie-Thread". Vermeiden Sie dies, da Jeder Zombie-Thread verbraucht einige Systemressourcen, und wenn genug Zombie-Threads haben sich angesammelt, es ist nicht mehr möglich, Neue Threads (oder Prozesse) erstellen.

Ein weiterer Punkt ist das Beibehalten des Hauptthreads im Status "defunct", während andere Threads ausgeführt werden, die zu implementierungsabhängigen Problemen bei verschiedenen Bedingungen führen können, z. B. wenn Ressourcen im Hauptthread zugewiesen werden oder Variablen, die lokal zum Hauptthread sind, in anderen Threads verwendet werden.

Außerdem werden alle freigegebenen Ressourcen nur freigegeben, wenn der Prozess beendet wird. Dadurch werden keine Ressourcen gespeichert. Ich denke also, dass die Verwendung von pthread_exit anstelle von pthread_join vermieden werden sollte.

0
Preeti