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.
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
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
Ques: What is the difference between Multithreading and Multiprocessing?
Ans: In a multiprocessing system, there is more than one processor, whereas in multithreading is a program execution technique which allows a single process to have multiple code segments. Multiprocessing improves the system's reliability, while in the multithreading process, each thread runs parallel to the other.
Ques: Give a real-life example where Multithreading is used?
Ans: In any social networking site like Instagram, when we log in, we can go to our feed where we can see stories from others, live videos, we can comment, or like the video, everything happens simultaneously, which is a form of multithreading.
Key Takeaways
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.