When to use pthread_exit() and when to use pthread_join() in Linux?

Solution 1:

As explained in the openpub documentations,

pthread_exit() will exit the thread that calls it.

In your case since the main calls it, main thread will terminate whereas your spawned threads will continue to execute. This is mostly used in cases where the main thread is only required to spawn threads and leave the threads to do their job

pthread_join will suspend execution of the thread that has called it unless the target thread terminates

This is useful in cases when you want to wait for thread/s to terminate before further processing in main thread.

Solution 2:

pthread_exit terminates the calling thread while pthread_join suspends execution of calling thread until target threads completes execution.

They are pretty much well explained in detail in the open group documentation:

  • pthread_exit
  • pthread_join

Solution 3:

Both methods ensure that your process doesn't end before all of your threads have ended.

The join method has your thread of the main function explicitly wait for all threads that are to be "joined".

The pthread_exit method terminates your main function and thread in a controlled way. main has the particularity that ending main otherwise would be terminating your whole process including all other threads.

For this to work, you have to be sure that none of your threads is using local variables that are declared inside them main function. The advantage of that method is that your main doesn't have to know all threads that have been started in your process, e.g because other threads have themselves created new threads that main doesn't know anything about.

Solution 4:

The pthread_exit() API

as has been already remarked, is used for the calling thread termination. After a call to that function a complicating clean up mechanism is started. When it completes the thread is terminated. The pthread_exit() API is also called implicitly when a call to the return() routine occurs in a thread created by pthread_create(). Actually, a call to return() and a call to pthread_exit() have the same impact, being called from a thread created by pthread_create().

It is very important to distinguish the initial thread, implicitly created when the main() function starts, and threads created by pthread_create(). A call to the return() routine from the main() function implicitly invokes the exit() system call and the entire process terminates. No thread clean up mechanism is started. A call to the pthread_exit() from the main() function causes the clean up mechanism to start and when it finishes its work the initial thread terminates.

What happens to the entire process (and to other threads) when pthread_exit() is called from the main() function depends on the PTHREAD implementation. For example, on IBM OS/400 implementation the entire process is terminated, including other threads, when pthread_exit() is called from the main() function. Other systems may behave differently. On most modern Linux machines a call to pthread_exit() from the initial thread does not terminate the entire process until all threads termination. Be careful using pthread_exit() from main(), if you want to write a portable application.

The pthread_join() API

is a convenient way to wait for a thread termination. You may write your own function that waits for a thread termination, perhaps more suitable to your application, instead of using pthread_join(). For example, it can be a function based on waiting on conditional variables.

I would recommend for reading a book of David R. Butenhof “Programming with POSIX Threads”. It explains the discussed topics (and more complicated things) very well (although some implementation details, such as pthread_exit usage in the main function, not always reflected in the book).

Solution 5:

You don't need any calls to pthread_exit(3) in your particular code.

In general, the main thread should not call pthread_exit, but should often call pthread_join(3) to wait for some other thread to finish.

In your PrintHello function, you don't need to call pthread_exit because it is implicit after returning from it.

So your code should rather be:

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);
      }
   }
}