C++ Multithreading is the process of multi tasking in C++ programming language. In real life, if a person performs two or more tasks at the same time, then this is called multi tasking. For example, if a person is driving car and at the same time attending calls then this multi tasking. This process is called multithreading in programming language.
Usually, the compiler runs a single program at one time but if it two or more than two programs concurrently then it is multithreading.
Types of Multitasking
There are two types of multitasking:
- Process based: It is the multitasking where computer deals with different programs running concurrently. Processes are independent of other processes. Here process refers to a single complete program.
- Thread based: It is the multitasking where computer deals with different parts of a single program running concurrently. Threads are dependent on each other. One thread transfers information to the other thread. Here thread refers to a piece of program.
POSIX Thread
Operating systems like Mac OS X, GNU/Linux OS and Solaris use POSIX to write multithread C++ programs.
Thread Creation
The syntax for writing a thread is:
#include <pthread.h> pthread_create (thread, attr, start_routine, arg)
The above code is referred to as routine that can be called multiple times. pthread.h is the header file that helps to create and execute threads. The method pthread_create() takes four input parameters. It creates the thread and the thread executes the sub routine. Upon creation, threads are passed a function to complete, and optionally some parameters for that function.
The first two attributes thread and attr are optional. The parameter thread is a unique identifier that returns a new thread after the execution of sub routine. The parameter attr is used to set the attributes of the thread. It can also be set to NULL. The parameter start_routine is the piece of code that the thread will execute. The parameter arg starts the routine. It is passed by reference as a pointer cast of type void. It can also be NULL.
Thread Termination
One thread can create other threads. The best practice is to terminate a thread after it is used. The syntax to terminate a POSIX thread is:
#include <pthread.h> pthread_exit (status)
The method pthread_exit() exits a thread. It is called after a thread is no longer needed.
For example, the below code creates five threads. Each thread takes function PrintText() as its argument. The PrintText() function prints the text “Welcome to tutorialsart!” with the number of thread executed. After the program executes all threads, it exits the threads.
#include <iostream> #include <cstdlib> #include <pthread.h> using namespace std; #define THREADS_QNTY 5 void *PrintText(void *threadNum) { long n; n = (long)threadNum; cout << "Welcome to tutorialsart! Thread Number: " << n << endl; pthread_exit(NULL); } int main () { pthread_t threads[THREADS_QNTY]; int x; int i; for( i = 0; i < THREADS_QNTY; i++ ) { cout << "creating thread, " << i << endl; x = pthread_create(&threads[i], NULL, PrintText, (void *)i); if (x) { cout << "Error: Thread cannot be created," << x << endl; exit(-1); } } pthread_exit(NULL); }
The output of the above code after compilation is:
C++ Multithreading
As clear from the name itself, multithreading means having multiple threads. C++ Multithreading works by creating and using threads. Each thread is a separate part of the program that is executed separately. Note that multithreading has nothing to do with the programming language. As it completely depends on the operating system OS of the machine.
C++ provides header file thread that contains threads and its relevant functions. The thread class is std::thread that defines a new thread and executes the code designated to the thread. The executable code that a thread contains is a callable object. To initiate a thread, programmer needs to create a new thread object. And then pass the callable object as the constructor of the thread object. After the object is created, it will start the thread and the thread will execute the code present in its callable.
A callable can be of three forms:
- A function pointer
- A function object
- A lambda expression
Creating thread using function pointer
The code below shows how to launch a thread using function pointer. The function is func() having return type void. The function parameters are written after the function name separated by comma while creating thread.
#include <thread> void func(arg) { // Piece of code } std::thread thread_obj(func, args);
Creating thread using function object
The code below shows how to launch a thread using function object. Here, thread_group is the class, func() is the overload operator. While creating a thread object, class object is passed followed with function arguments separated by comma.
#include <thread> class thread_group { void func()(args) { // Piece of code } } std::thread thread_object(thread_group(), args)
Creating thread using lambda expression
The code below shows how to launch a thread using lambda expression. After defining a lambda function, the program uses lambda expression and its parameters args in thread creation as object constructor.
#include <thread> auto func = [](args) { // Piece of code }; std::thread thread_object(func, args);
Advantages of C++ Multithreading
Each thread has its own identity and task as each individual thread can complete only one function at a time. C++ Multithreading provides code reusability. As thread groups allow user to recycle and reuse thread objects to give programs the functionality of unlimited multitasking. Not only does this take advantage of multiple CPU cores, but it also allows the programmer to control the number of tasks taken on by manipulating the thread group size. The program can then use the computer resources efficiently without overloading becoming overloaded.
The outcome of the single thread example can be easily replicated using multithreaded code. Here programmer can see the benefits of multithreading as the programmer can attempt to execute print function multiple times with different sets of data. Without multithreading, this would be done by simply using the loop statements to repeat print functions one at a time until completion.