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