What are pthreads in C/C++?

Overview

pthreads or POSIX threads are an implementation of the thread API for C/C++. It allows the spawning of new concurrent process flows and the multithreading system, which allows parallel and distributed processing. It does so by dividing the program into subtasks whose execution can be interleaved to run in parallel.

To utilize the pthread interface, we must include its header file. We'll consider the C language for the following example. We include the pthread header file using the following piece of code:

#include <pthread.h>

Syntax

We use the pthread_create to create POSIX threads:

pthread_create(&thread, NULL, FunctionName, NULL);

Parameters

This function has the following arguments:

  1. Thread identifier: The location where the ID of the newly created thread will be stored, &thread.
  2. Thread attributes: The thread attribute object specifying the attributes for the thread that is being created. If attributes are NULL, it creates the thread using default settings.
  3. Function to run: This is the location of the function or in simple terms, the function name the thread is to run, FunctionName.
  4. Function arguments: These are the function arguments for the function the thread is running, NULL.

Below is a sample code to create pthread with a sample function:

// Importing the Pthread Library
#include <pthread.h>
// Importing the library for printf
#include <stdio.h>

// This function takes in a pointer 
void * ThreadFunction(void *arguments)
{
  printf("Thread Running\n");
  return NULL;
}

int main() {
  
  // Creating the Location where the ID of the newly created 
  // thread will be stored
  pthread_t thread1;

  printf("Calling Thread \n");
  
  // Creating the thread
  pthread_create(&thread1, NULL, ThreadFunction, NULL);
  return 0;
}
Demonstration of pthread_create function

Explanation

We import the necessary libraries:

// Importing the Pthread Library
#include <pthread.h>
// Importing the library for printf
#include <stdio.h>

We declare a ThreadFunction function that the thread function will execute:

// This function takes in a pointer
void * ThreadFunction(void *arguments)
{
printf("Thread Running\n");
return NULL;
}

We create the location where the ID of the newly created thread will be stored:

pthread_t thread1;

We create the thread. Here, the first argument is the location of the thread identifier. The second argument is the thread attributes which are NULL here. The third argument is the function name this thread will execute and the last argument is the parameters we pass to this function, which in this case are NULL.

pthread_create(&thread1, NULL, ThreadFunction, NULL);

pthreads are employed in multiprocessor systems and can improve the overall performance of the program by employing the use of parallelism but they must be used carefully in code because they are prone to the race condition. In the above pthread_create the output of the function is non deterministic and depends on how threads are scheduled on the CPU. If the main thread is scheduled to execute before the newly created thread, the newly thread will not execute. Since this thread scheduling depends on CPU scheduling which is non deterministic we can not say for sure when and if the thread will be executed. This is known as race conditions. To avoid this we use pthread_join .