POSIX: Detached vs Joinable threads | pthread_join() & pthread_detach() Examples

Guys who are looking for the perfect guide or tutorial for POSIX: Detached vs Joinable threads and pthread_join() & pthread_detach() examples? Can stay with us. This tutorial will explain & give you complete guidance while programming by using these Detached & Joinable Threads. Before going to learn Detached vs Joinable threads along with pthread_join() & pthread_detach() examples let’s start understanding what is thread and pthread?

About threads

A thread is a semi-process that has its own stack and executes a given piece of code. threads within the same process run in shared memory space, it defined as an independent stream of instructions that can be scheduled to run as such by the operating system.

What is pthreads?

POSIX Threads usually referred to as pthreads, is an execution model that exists independently from a language, as well as a parallel execution model. It allows a program to control multiple different flows of work that overlap in time.

Thread can be run in two modes. They are as such,

1. Joinable mode
2. Detached mode

Joinable Thread & pthread_join()

A joinable thread will not release any resource even after the end of the thread function until some other thread calls pthread_join() with its ID.

Whereas pthread_join() is a blocking call, it will block the calling thread until the other thread ends.

We will pass two parameters in pthread-

1. The ID of the target thread

2. Address of (void *) i.e. (void **), it will point to the return value of thread function i.e. pointer to (void *).

pthread_join() will return non-zero value in case of error.

Example of pthread_join()

Below is the example for joinable thread,

#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
void * threadFunc(void * arg)
{
    std::cout << "Thread Function :: Start" << std::endl;
    // Sleep for 2 seconds
    sleep(2);
    std::cout << "Thread Function :: End" << std::endl;
    // Return value from thread
    return new int(6);
}
int main()
{
    // Thread id
    pthread_t threadId;
    // Create a thread that will funtion threadFunc()
    int err = pthread_create(&threadId, NULL, &threadFunc, NULL);
    // Check if thread is created sucessfuly
    if (err)
    {
        std::cout << "Thread creation failed : " << strerror(err);
        return err;
    }
    else
        std::cout << "Thread Created with ID : " << threadId << std::endl;
    // Do some stuff
    void * ptr = NULL;
    std::cout << "Waiting for thread to exit" << std::endl;
    // Wait for thread to exit
    err = pthread_join(threadId, &ptr);
    if (err)
    {
        std::cout << "Failed to join Thread : " << strerror(err) << std::endl;
        return err;
    }
    if (ptr)
        std::cout << " value returned by thread : " << *(int *) ptr
                << std::endl;
    delete (int *) ptr;
    return 0;
}

Output:

Thread Created with ID : 1407020804273336
Waiting for thread to exit
Thread Function :: Start
Thread Function :: End
value returned by thread : 6

Also Check:

Detached Thread & pthread_detach()

By default all threads are joinable, we will call pthread_detach() so to make a thread detached. A Detached thread automatically releases its allocated resources on exit. No other thread needs to join it.

#include <pthread.h>

int pthread_detach(pthread_t thread);

There is no way to determine its return value of the detached thread function.
pthread_detach() will return non zero value in case of error.

Output can change on your system because both the main and thread functions are running in parallel.

If the main function exits then all other threads will be exited.

pthread_detach() Example

Below is the example,

#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
void * threadFunc(void * arg)
{
    std::cout << "Thread Function :: Start" << std::endl;
    std::cout << "Thread Function :: End" << std::endl;
    // Return value from thread
    return NULL;
}
int main()
{
    // Thread id
    pthread_t threadId;
    // Create a thread that will funtion threadFunc()
    int err = pthread_create(&threadId, NULL, &threadFunc, NULL);
    // Check if thread is created sucessfuly
    if (err)
    {
        std::cout << "Thread creation failed : " << strerror(err);
        return err;
    }
    else
        std::cout << "Thread Created with ID : " << threadId << std::endl;
    // Do some stuff
    err = pthread_detach(threadId);
    if (err)
        std::cout << "Failed to detach Thread : " << strerror(err) << std::endl;
    // Sleep for 2 seconds because if main function exits, then other threads will
    // be also be killed. Sleep for 2 seconds, so that detached exits by then
    sleep(2);
    std::cout << "Main function ends " << std::endl;
    return 0;
}

Output:

Thread Created with ID : 139703273027328
Thread Function :: Start
Thread Function :: End
Main function ends