Table of contents
1.
Introduction
2.
What is a Thread?
3.
What is Multithreading?
4.
Why do Multithreading?
5.
Creating a Thread
6.
Terms used in the above syntax:
7.
Terminating a Thread
8.
Launching Thread Using Function Pointer
9.
Launching Thread Using Lambda Expression
10.
Launching Thread Using Function Objects
11.
Launching Thread Using Non-Static Member Function
12.
Launching Thread Using Static Member Function
13.
Passing argument to threads
14.
Joinable and Not Joinable Threads: Explanation
15.
Joining and Detaching threads
16.
Frequently Asked Questions
16.1.
Is C++ good for multithreading?
16.2.
What is multithreading in C++ explain?
16.3.
Is multithreading hard in C++?
17.
Conclusion
Last Updated: Nov 27, 2024
Easy

Multithreading in C++

Career growth poll
Do you think IIT Guwahati certified course can help you in your career?

Introduction

Multithreading in C++ is a powerful concept that allows multiple threads to run concurrently within a program, enhancing performance by utilizing CPU cores efficiently. It enables tasks like parallel execution, faster data processing, and responsive applications. Multithreading is essential for real-time systems, gaming, and complex computations.

Multithreading in C++

In this article, we'll explore what multithreading is, how it works in C++, and provide examples to demonstrate its effective use in your programs.

Also see, Literals in C.Fibonacci Series in C++

What is a Thread?

A thread is defined as the single sequence stream within a process, which is also called a lightweight process. Each thread executes different parts of the program, but each thread shares the same memory and system resources. The pthread.h header file has all the thread functions.

What is Multithreading?

Multithreading is the same as multitasking, i.e., it allows multiple threads/tasks to run simultaneously on your system. Each thread handles and represents a different task. C++ does not contain any built-in support for multithreading applications, and it relies completely on the operating system for it.

There are two types of multitasking:

  • Process-based multitasking: this handles/maintains the concurrent execution of programs.
  • Thread-based multitasking: this deals with the concurrent execution of pieces of the same program.

 

For example: in a browser, multiple tabs are running simultaneously, each tab can be represented as a thread.

Why do Multithreading?

Multithreading is done using threads which are preferred over processes because

  • Each thread has its own program counter, a register set, and a stack space
  • Creating a thread is much faster.
  • Switching context between threads is simpler and faster
  • They can be terminated easily
  • Communication between threads is faster

 

Multithreading performs faster on a multi CPU system. This helps in reducing the performance and concurrency. It also helps the programmer to access multiple applications simultaneously and enables the program to make the best use of the available CPU.

Creating a Thread

The “pthread.h” header file contains all the functions which are required for working with threads. The pthread_create() function is used to create a thread and makes it executable.

This can be called any number of times and from anywhere in the code. The maximum number of threads which can be created is implementation-dependent. 

Syntax

pthread_create( Id_thread, attr, start_routine, arg)

Terms used in the above syntax:

  • Id_thread: it is an opaque and unique identifier for each thread which is returned by the subroutine.
  • attr: it is an attribute object that is used to set multiple thread attributes. We can provide thread attribute objects or we can set it to NULL for default values.
  • start_routine: it is a C++ routine that the thread will execute once it is created.
  • arg it is a single argument that is passed to start_routine. If we don't pass any argument, then by default, it will pass NULL. The arg must be passed by reference as a pointer of type void.

Terminating a Thread

Any thread can be terminated by using the pthread_exit() function,it is used to explicitly exit a thread. This is called once the thread has completed its work and is no longer required.

Syntax

pthread_exit (status)

 

Example

#include <iostream>
#include <cstdlib>
#include <pthread.h>

using namespace std;
#define thread_count 2

void *Display(void *thread_id) {
  long id;
  id = (long)thread_id;
  cout << "Hello World! from thread : " << id+1 << endl;
  pthread_exit(NULL);
}

int main () {
  pthread_t thread_array[thread_count];
  int rc;
  
  for(int i = 0; i < thread_count; i++ ) 
  {
        cout << "Thread Created : " << i+1 << endl;
        rc = pthread_create(&thread_array[i], NULL, Display, (void *)i);
        
        if (rc) {
            cout << "Error in creating thread :" << rc << endl;
            exit(-1);
        }
  }
  pthread_exit(NULL);
}

 

Output

Thread Created : 1
Thread Created : 2
Hello World! from thread : 1
Hello World! from thread : 2

 

You practice by yourself with the help of online c++ compiler.

Launching Thread Using Function Pointer

In C++, you can launch a thread using a function pointer by passing the function's address to the std::thread constructor. This is a simple way to create a thread when the task to execute is a regular function.

Example:

#include <iostream>  
#include <thread>  

void printMessage() {  
    std::cout << "Thread using function pointer.\n";  
}  

int main() {  
    std::thread t(printMessage);  
    t.join();  
    return 0;  
}  
You can also try this code with Online C++ Compiler
Run Code


Explanation:
Here, the std::thread is created by passing the printMessage function pointer. The join() method ensures the main thread waits for t to complete.

Launching Thread Using Lambda Expression

A lambda expression allows inline function definition, making it easier to define and launch short-lived tasks without a separate function declaration.

Example:

#include <iostream>  
#include <thread>  

int main() {  
    std::thread t([]() { std::cout << "Thread using lambda expression.\n"; });  
    t.join();  
    return 0;  
}  
You can also try this code with Online C++ Compiler
Run Code


Explanation:
The lambda expression []() defines an anonymous function inline. The std::thread executes this function concurrently.

Launching Thread Using Function Objects

Function objects (functors) are objects with an overloaded operator(), allowing them to behave like functions.

Example:

#include <iostream>  
#include <thread>  

class PrintMessage {  
public:  
    void operator()() {  
        std::cout << "Thread using function object.\n";  
    }  
};  

int main() {  
    PrintMessage pm;  
    std::thread t(pm);  
    t.join();  
    return 0;  
}  
You can also try this code with Online C++ Compiler
Run Code


Explanation:
PrintMessage is a class with an overloaded operator(). The std::thread takes the object pm and executes it like a function.

Launching Thread Using Non-Static Member Function

A non-static member function requires an instance of the class to be invoked by the thread.

Example:

#include <iostream>  
#include <thread>  

class MyClass {  
public:  
    void printMessage() {  
        std::cout << "Thread using non-static member function.\n";  
    }  
};  

int main() {  
    MyClass obj;  
    std::thread t(&MyClass::printMessage, &obj);  
    t.join();  
    return 0;  
}  
You can also try this code with Online C++ Compiler
Run Code


Explanation:
The std::thread is created using the member function pointer &MyClass::printMessage and an instance obj.

Launching Thread Using Static Member Function

A static member function belongs to the class, not an instance, making it callable without an object and suitable for threading.

Example:

#include <iostream>  
#include <thread>  

class MyClass {  
public:  
    static void printMessage() {  
        std::cout << "Thread using static member function.\n";  
    }  
};  

int main() {  
    std::thread t(&MyClass::printMessage);  
    t.join();  
    return 0;  
}  
You can also try this code with Online C++ Compiler
Run Code


Explanation:
Here, the std::thread calls the static function directly using &MyClass::printMessage without needing an instance of MyClass.

Passing argument to threads

We can pass multiple arguments to the thread created using pthread_create() function with the help of structure.

Example

#include <iostream>
#include <cstdlib>
#include <pthread.h>

using namespace std;

#define thread_count 2

struct info{
  int  threadId;
  char *msg;
};

void *Print(void *thread_arg) 
{
    struct info *obj;
    obj = (struct info *) thread_arg;
    cout<<obj->msg<<" "<<obj->threadId<<endl;
    pthread_exit(NULL);
}

int main () {
    pthread_t threads[thread_count];
    struct info td[thread_count];
    int rc;

    for(int i = 0; i < thread_count; i++ ) {
    cout <<"Thread created with Id : " << i+1 << endl;
    td[i].threadId = i+1;
    td[i].msg = "Hello from Thread :";
    rc = pthread_create(&threads[i], NULL, Print, (void *)&td[i]);

    if (rc) {
        cout << "Error:unable to create thread," << rc << endl;
        exit(0);
    }
    }
    pthread_exit(NULL);
} 

 

Output

Thread created with Id : 1
Thread created with Id : 2
Hello from Thread : 1
Hello from Thread : 2

Joinable and Not Joinable Threads: Explanation

In multithreading, a thread can be either joinable or detached:

  1. Joinable Threads: The calling thread waits for the thread to finish using pthread_join(). This ensures synchronization and proper cleanup of resources.
     
  2. Detached Threads: The thread executes independently, without blocking the main thread. Once completed, the system automatically reclaims its resources, using pthread_detach().

Joining and Detaching threads

The pthread_join() function is used to join a thread. It blocks the calling thread until the ‘threadid’ thread terminates, i.e., the main thread will terminate once the child thread is terminated. During the creation of a thread, one of the attributes defines whether it is joinable or detached, that is, only threads which are created as joinable can be joined. If a thread is created as detached, then it can never be joined.

Syntax for joining

pthread_join(threadid, status)

 

Example of join()

#include <iostream>
#include <unistd.h>  
#include <pthread.h>
using namespace std;

string str;
void* auxiliary(void*)
{
  sleep(1);   
  cout << "Child thread created " << str << endl;
}

int main()
{
    pthread_t thread_array[2];
    for(int i=0; i<2; i++)
    {
        cout << "Thread created with id: " << i+1 << str << endl;
        pthread_create(&thread_array[i], NULL, &auxiliary, NULL);
        pthread_join(thread_array[i], NULL);
    }
    exit(EXIT_SUCCESS);
    return 0;
}

 

Output

Thread created with id: 1
Child thread created 
Thread created with id: 2
Child thread created 

 

The pthread_detach() function is used to detach a thread from the parent thread. In this, the main and child thread are executed independently.

Syntax of detach 

pthread_detach(threadid)

 

Example of detach()

#include <iostream>
#include <unistd.h>   
#include <pthread.h>
using namespace std;

string str;
void* auxiliary(void*)
{
  sleep(1);  
  cout << "Child thread created" << str << endl;
}

int main()
{
    pthread_t thread_array[2];
    for(int i=0; i<2; i++)
    {
        cout << "Thread created with id: " << i+1 << str << endl;
        pthread_create(&thread_array[i], NULL, &auxiliary, NULL);
        pthread_detach(thread_array[i]);
    }
    exit(EXIT_SUCCESS);
    return 0;
}

 

Output

Thread created with id: 1
Thread created with id: 2

You can also check out Multithreading in C# here.

Frequently Asked Questions

Is C++ good for multithreading?

Yes, C++ is good for multithreading as it provides the <thread> library, supporting efficient thread management, synchronization, and concurrency features for modern applications.

What is multithreading in C++ explain?

Multithreading in C++ allows concurrent execution of multiple threads, enabling better CPU utilization and faster performance for tasks like data processing or computation.

Is multithreading hard in C++?

Multithreading in C++ can be challenging due to complexities like thread synchronization, race conditions, and deadlocks, but libraries like <thread> simplify implementation.

Conclusion

In this blog, we have covered the following things:

  • First, we discussed what multithreading in C++ is.
  • Then we discussed how we can create threads, terminate threads, pass arguments to threads, join and detach threads with examples.

Check out this article - C++ String Concatenation

Recommended Readings:

C++ is an object-oriented programming language that has many more features which are as useful and powerful as multithreading. Java also supports multithreading like C++, to learn more about the similarities and differences between C++ and Java, refer to this

Classes are the fundamental block of C++ which are used to implement the concepts of object-oriented programming in order to study more about object-oriented programming in detail refer to this

Live masterclass