pthread_join() for asynchronous threads

16.6k views Asked by At

I have written a simple demonstration program so that I can understand the pthread_join() function.

I know how to use the pthread_condition_wait() function to allow asynchronous threading but I'm trying to understand how I can do similar work using the pthread_join() function.

In the program below I pass Thread 1s ID to Thread 2s function. Inside Thread 2s function I call the pthread_join() function and pass in Thread 1s ID. I expected this to cause Thread 1 to run first and then for Thread 2 to run second, but what I'm getting is that they both run concurrently.

Is this because only one thread can use the pthread_join() function at a time and that I am already using the pthread_join() function when I call it from the main thread?

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

void *functionCount1();
void *functionCount2(void*);

int main()
{

    /* 
        How to Compile
         gcc -c foo
         gcc -pthread -o foo foo.o
    */

    printf("\n\n");

    int rc;
    pthread_t thread1, thread2;

    /* Create two thread --I took out error checking for clarity*/
    pthread_create( &thread1, NULL, &functionCount1, NULL)
    pthread_create( &thread2, NULL, &functionCount2, &thread1)

    pthread_join( thread1, NULL);
    pthread_join( thread2, NULL);

    printf("\n\n");
    exit(0);
}

void *functionCount1()
{

    printf("\nFunction 1");
        sleep(5);
    printf("\nFunction 1");

    return(NULL);
}

void *functionCount2(void* argument)
{

    pthread_t* threadID = (pthread_t*) argument;

    pthread_join(*threadID, NULL);

    printf("\nFunction 2");
        sleep(5);
    printf("\nFunction 2");

    return(NULL);
}

Output:

enter image description here

3

There are 3 answers

2
P.P On BEST ANSWER

When threads are created using pthread_create(), both threads start execution concurrently and there's no fixed ordering on their order of execution. The order depends on the OS scheduling and number of processors available etc. In any case, that can't be determined and that's the point of threads anyway.

What happens when you call pthread_join(), the caller waits for thread that join with to terminate. So main thread waits for thread1 to terminate and then for thread2. But while main waits for thread1, thread2 might have finished execution and terminated already. In this case, pthread_join(thread2, NULL); would return immediately.

You have a bigger problem in your code. You are passing thread1's ID to thread2. But if thread1 finished execution before thread2 starts, then you are going be using an invalid thread identifier, leading to undefined behaviour. Another problem is that your main thread and thread2 both trying to join with thread1. In short, pthread_join() is not the right tool for synchronization between multiple threads. As you stated, you be using conditional variable/mutexes for this purpose.

I suggest, you remove pthread_join() from thread2, to fix undefined behaviour and if you want serial execution of threads, then you have to create threads one after another and let them and wait for the previous thread to terminate (pthread_join()). But there's very little practical use in doing this. Or let the threads wait on a conditional variable before doing anything and you can make the threads communicate in the order you desire using conditional variables.

0
rowan.G On

You invoke undefined behavior. the man page: http://man7.org/linux/man-pages/man3/pthread_join.3.html

Joining with a thread that has previously been joined results in undefined behavior.

Also the first thread might finish exectution before the second thread. If you want something like this it is alot better to use pthread_cond_wait().

0
didierc On

From the pthread_join man page(emphasis mine):

If multiple threads simultaneously try to join with the same thread, the results are undefined. If the thread calling pthread_join() is canceled, then the target thread will remain joinable (i.e., it will not be detached).

It seems that you are exactly in this situation, with main thread and thread 2 both trying to pthread_join thread 1.

You should clearly define for each thread a single "owner thread " which is responsible for its management. The chain of responsibility should form a hierarchical tree of thread (ie no cycles or multiple parents).