Why and how to use `pthread_join()`? - PThreads
- Q: What is join with respect to Pthreads?
A: Join is a functionality of Pthread library which allows the originating thread to wait for the completion of all its spawned thread's tasks.
Without join the originating thread would exit as soon as it completes its chores, completely ignoring the states of its spawned threads. Due to this, even if any of the spawned threads is in middle of its chore, it'll simply get aborted. - Problem statement:
In the below code I have created 10 threads. Each of those threads is supposed to print the value of the variable contained in their argument function and then exit.
Code:#include <pthread.h> #include <iostream> /* Declaration of the function which will serve as an argument function for all the threads.*/ void* functionA (void*); /* Declaration of the global variable which will get incremented by each of the threads in the common function `functionA`.*/ int counter = 0; /* Declaration and initialization of the mutex variable which will protect the shared global variable `counter`.*/ pthread_mutex_t mutexA = PTHREAD_MUTEX_INITIALIZER; int main () { /* Declaring an array for 10 threads.*/ pthread_t thread_id [10]; /* Creating 10 threads with default attributes and the common function namely `functionA` for execution.*/ for (int i = 0; i < 10; i++) { pthread_create (&thread_id [i], NULL, functionA, NULL); } std :: cout << "Final counter value: " << counter << "\n"; return 0; } void* functionA (void* arg) { /* `pthread_self ()` prints the thread ID of the currently calling thread.*/ std :: cout << "Thread number: " << pthread_self () << "\n"; pthread_mutex_lock (&mutexA); /* Each time this function gets called, the counter is incremented by the calling thread.*/ counter++; pthread_mutex_unlock (&mutexA); return 0; }
Code:anisha@linux-y3pi:~/> g++ joinA.cpp -lpthread -Wall anisha@linux-y3pi:~/> ./a.out Final counter value: 0 anisha@linux-y3pi:~/>
The job of the thread executing the function `main ()` was to create 10 threads, print the value of the variable `counter`, and return 0. That's exactly what it did. We didn't tell it to "wait" for its 10 spawned threads to finish their chores! Did we?
When there are multiple threads involved, the kernel schedules all the threads giving each one of them certain time to execute based on some scheduling algorithm. If and when, the thread executing the function `main ()` gets scheduled by the kernel before the other threads, it will try to complete its chore and return in the given time! If it returns before its spawned threads, the spawned threads will get aborted. That's what has happened here! - Solution:
Code:int pthread_join (pthread_t threadID, void* *retval);
The exit status of the thread is copied in the argument `retval`. If the target thread was canceled, then `PTHREAD_CANCELED` is placed in `retval`.
If multiple threads simultaneously try to join with the same thread, then the results are undefined.
On success, `pthread_join()` returns 0; on error, it returns an error number.
Code:#include <pthread.h> #include <iostream> /* Declaration of the function which will serve as an argument function for all the threads.*/ void* functionA (void*); /* Declaration of the global variable which will get incremented by each of the threads in the common function `functionA`.*/ int counter = 0; /* Declaration and initialization of the mutex variable which will protect the shared global variable `counter`.*/ pthread_mutex_t mutexA = PTHREAD_MUTEX_INITIALIZER; int main () { /* Declaring an array for 10 threads.*/ pthread_t thread_id [10]; /* Creating 10 threads with default attributes and the common function namely `functionA` for execution.*/ for (int i = 0; i < 10; i++) { pthread_create (&thread_id [i], NULL, functionA, NULL); } /* Telling the main thread to wait for the task completion of all its spawned threads.*/ for (int j = 0; j < 10; j++) { pthread_join (thread_id [j], NULL); } std :: cout << "\n\nFinal counter value: " << counter << "\n"; return 0; } void* functionA (void* arg) { /* `pthread_self ()` prints the thread ID of the currently calling thread.*/ std :: cout << "Thread number: " << pthread_self () << "\n"; pthread_mutex_lock (&mutexA); /* Each time this function gets called, the counter is incremented by the calling thread.*/ counter++; pthread_mutex_unlock (&mutexA); return 0; }
Code:anisha@linux-y3pi:~/> g++ joinB.cpp -lpthread -Wall anisha@linux-y3pi:~/> ./a.out Thread number: 140546115806992 Thread number: 140546107414288 Thread number: 140546099021584 Thread number: 140546090628880 Thread number: 140546082236176 Thread number: 140546073843472 Thread number: 140546065450768 Thread number: 140546124199696 Thread number: 140546132592400 Thread number: 140546140985104 Final counter value: 10 anisha@linux-y3pi:~/>
Total Comments 0