Multithreading in C++

  • November 3, 2022
  • C++
Accessing Elements
What is Multithreading?

Multithreading is a subset of multitasking, which is the feature that allows your computer to run two or more programs at the same time. Multitasking is classified into two types: process-based and thread-based.

What is a Thread?

A multithreaded program has two or more parts that can run simultaneously. Each component of such a program is referred to as a thread, and each thread defines a distinct execution path. Each thread shares memory, file descriptors, and other system resources. std::thread is the thread class that represents a single thread in C++

Creating Threads :

The given code launches three threads from the main function.


#include <iostream>
#include <thread>
using namespace std;

void func1(int Z)
{
	for (int i = 0; i < Z; i++) {
		cout << "Thread using function"
			" pointer as callable\n";
	}
}

// A callable object
class thread_obj {
public:
	void operator()(int x)
	{
		for (int i = 0; i < x; i++)
			cout << "Thread using function"
				" object as callable\n";
	}
};

int main()
{
	cout << "Threads 1 and 2 and 3 "
		"operating independently" << endl;

	// function pointer as callable
	thread th1(func1, 3);

	// function object as callable
	thread th2(thread_obj(), 3);

	// Define a Lambda Expression
	auto f = [](int x) {
		for (int i = 0; i < x; i++)
			cout << "Thread using lambda"
			" expression as callable\n";
	};
	// lamda expression as callable
	thread th3(f, 3);

	// Wait for the threads to finish
	// Wait for thread t1 to finish
	th1.join();

	// Wait for thread t2 to finish
	th2.join();

	// Wait for thread t3 to finish
	th3.join();

	return 0;
}
Output:
Threads 1 and 2 and 3 operating independently                                                       
Thread using function pointer as callable                                                           
Thread using lambda expression as callable                                                          
Thread using function pointer as callable                                                           
Thread using lambda expression as callable                                                          
Thread using function object as  callable                                                          
Thread using lambda expression as callable                                                          
Thread using function pointer as callable                                                          
Thread using function object as  callable                                                           
Thread using function object as  callable
Joining and Detaching Threads:

We can use the following two procedures to join or detach threads:

join() function:

The join() function of the thread class is used to join a thread. It intertwines the main thread and the child thread. The main thread terminates only after the child thread has completed its execution, i.e. the main thread waits for the child thread to complete its execution. Only threads that are created as joinable can be joined. If a thread is created as detached, it can never be joined.

Syntax:

threadname.join();
detach() function:

The detach() function separates a thread from its parent. It enables the main thread and the child thread to run independently.

Syntax:

threadname.detach();
Example:

This example shows how to use the Pthread join routine to wait for thread completions.

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

using namespace std;

#define NUM_THREADS 5

void *wait(void *t) {
   int i;
   long tid;

   tid = (long)t;

   sleep(1);
   cout << "Sleeping in thread " << endl;
   cout << "Thread with id : " << tid << "  ...exiting " << endl;
   pthread_exit(NULL);
}

int main () {
   int rc;
   int i;
   pthread_t threads[NUM_THREADS];
   pthread_attr_t attr;
   void *status;

   // Initialize and set thread joinable
   pthread_attr_init(&attr);
   pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

   for( i = 0; i < NUM_THREADS; i++ ) {
      cout << "main() : creating thread, " << i << endl;
      rc = pthread_create(&threads[i], &attr, wait, (void *)i );
      if (rc) {
         cout << "Error:unable to create thread," << rc << endl;
         exit(-1);
      }
   }

   // free attribute and wait for the other threads
   pthread_attr_destroy(&attr);
   for( i = 0; i < NUM_THREADS; i++ ) {
      rc = pthread_join(threads[i], &status);
      if (rc) {
         cout << "Error:unable to join," << rc << endl;
         exit(-1);
      }
      cout << "Main: completed thread id :" << i ;
      cout << "  exiting with status :" << status << endl;
   }

   cout << "Main: program exiting." << endl;
   pthread_exit(NULL);
}
Output:
main() : creating thread, 0
main() : creating thread, 1
main() : creating thread, 2
main() : creating thread, 3
main() : creating thread, 4
Sleeping in thread
Thread with id : 0 .... exiting
Sleeping in thread
Thread with id : 1 .... exiting
Sleeping in thread
Thread with id : 2 .... exiting
Sleeping in thread
Thread with id : 3 .... exiting
Sleeping in thread
Thread with id : 4 .... exiting
Main: completed thread id :0  exiting with status :0
Main: completed thread id :1  exiting with status :0
Main: completed thread id :2  exiting with status :0
Main: completed thread id :3  exiting with status :0
Main: completed thread id :4  exiting with status :0
Main: program exiting.

Note: also read about Memory Management in C++

Follow Me

Please follow me to read my latest post on programming and technology if you like my post.

https://www.instagram.com/coderz.py/

https://www.facebook.com/coderz.py

Leave a Reply

Your email address will not be published. Required fields are marked *