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:
- Joinable Threads: The calling thread waits for the thread to finish using pthread_join(). This ensures synchronization and proper cleanup of resources.
- 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.