LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
Go Back   LinuxQuestions.org > Blogs > TheIndependentAquarius
User Name
Password

Notices

Rating: 2 votes, 5.00 average.

Why and how to use `pthread_join()`? - PThreads

Posted 05-23-2012 at 01:00 AM by TheIndependentAquarius
Updated 08-24-2012 at 01:50 AM by TheIndependentAquarius

  • 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;
    } 
    Output:
    Code:
    anisha@linux-y3pi:~/> g++ joinA.cpp -lpthread -Wall
    anisha@linux-y3pi:~/> ./a.out 
    
    Final counter value: 0
    
    anisha@linux-y3pi:~/>
    Observation:
    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 argument `threadID` holds the ID of the thread to be joined.
    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;
    }
    Output:
    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:~/>
Posted in PThreads
Views 4445 Comments 0
« Prev     Main     Next »
Total Comments 0

Comments

 

  



All times are GMT -5. The time now is 05:33 PM.

Main Menu
Advertisement

My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration