Related Articles

# Non-Repeating Elements of a given array using Multithreaded program

• Difficulty Level : Medium
• Last Updated : 09 Jul, 2021

Given an array arr[] of size N and an integer T representing the count of threads, the task is to find all non-repeating array elements using multithreading.

Examples:

Input: arr[] = { 1, 0, 5, 5, 2}, T = 3
Output: 0 1 2
Explanation:
The frequency of 0 in the array arr[] is 1.
The frequency of 1 in the array arr[] is 1.
The frequency of 2 in the array arr[] is 1.
Therefore, the required output is 0 1 2

Input: arr[] = { 1, 1, 5, 5, 2, 4 }, T = 3
Output: 2 4
Explanation:
The frequency of 2 in the array arr[] is 1.
The frequency of 4 in the array arr[] is 1.
Therefore, the required output is 2 4

Approach: The idea is to use the pthread library available in C++ to create multiple threads for concurrent process flow and perform multiple operations( pthread create, pthread join , lock, etc) in multithreaded program. Follow the steps below to solve the problem:

• Divide the array into T subarrays, such that each subarray of size N / T will be executed in a single thread.
• Initialize a Map, say mp, to store the frequencies of each array element.
• Create a pthread_mutex_lock, say lock1, to ensure that all threads do not trip over each other and corrupt the Map container.
• Define a function func() for executing the body of a thread. This function is often called the kernel of the thread and is provided during thread creation.
• Lock the current thread using pthread_mutex_lock() so that it does not overlap with other threads
• Traverse through the given range as an argument to the function func() in the array arr[] and increment the frequency of the array element which is encountered.
• Release the current thread using the function pthread_mutex_unlock().
• Initialize an array, say thread[], of type pthread_t for storing the threads.
• Iterate over the range [0, T] and create a thread by calling pthread_create() function and store it in the thread[i]
• While each thread performs their individual tasks, the main() function will need to wait till each of the threads finish their work.
• Use pthread_join() function for waiting till each thread finishes executing function func()
• Iterate over the range [0, T] and call pthread_create() function for each thread[i]
• Finally, traverse the map mp and print the element occurring only once.

Below is the implementation of the above approach:

## C++

 `// C++ program to implement``// the above approach` `#include ``#include ``using` `namespace` `std;` `// Structure of subarray``// of the array``struct` `range_info {` `    ``// Stores start index``    ``// of the subarray``    ``int` `start;` `    ``// Stores end index``    ``// of the subarray``    ``int` `end;` `    ``// Stores pointer to the``    ``// first array element``    ``int``* a;``};`  `// Declaring map, and mutex for``// thread exclusion(lock)``map<``int``, ``int``> mp;``pthread_mutex_t lock1;`  `// Function performed by every thread to``// count the frequency of array elements``// in current subarray``void``* func(``void``* arg)``{``    ``// Taking a lock so that threads``    ``// do not overlap each other``    ``pthread_mutex_lock(&lock1);``    ` `    ` `    ``// Initialize range_info``    ``// for each thread``    ``struct` `range_info* rptr``    ``= (``struct` `range_info*)arg;`  `    ``// Thread is going through the array``    ``// to check and update the map``    ``for` `(``int` `i = rptr->start;``            ``i <= rptr->end; i++) {``                    ` `        ` `        ``// Stores iterator to the map        ``        ``map<``int``, ``int``>::iterator it;``        ` `        ` `        ``// Update it``        ``it = mp.find(rptr->a[i]);``        ` `        ` `        ``// If rptr->a[i] not found``        ``// in map mp``        ``if` `(it == mp.end()) {``            ` `            ` `            ``// Insert rptr->a[i] with``            ``// frequency 1``            ``mp.insert({ rptr->a[i], 1 });``        ``}``        ``else` `{``            ` `            ` `            ``// Update frequency of``            ``// current element``            ``it->second++;``        ``}``    ``}``    `  `    ``// Thread releases the lock``    ``pthread_mutex_unlock(&lock1);``    ``return` `NULL;``}`  `// Function to find the unique``// numbers in the array``void` `numbers_occuring_once(``int` `arr[],``                        ``int` `N, ``int` `T)``{``    ``// Stores all threads``    ``pthread_t threads[T];` `    ``// Stores start index of``    ``// first thread``    ``int` `spos = 0;` `    ``// Stores last index``    ``// of the first thread``    ``int` `epos = spos + (N / T) - 1;` `    ``// Traverse each thread``    ``for` `(``int` `i = 0; i < T; i++) {` `        ``// Initialize range_info for``        ``// current thread``        ``struct` `range_info* rptr``            ``= (``struct` `range_info*)``malloc``(``                ``sizeof``(``struct` `range_info));` `        ``// Update start index of``        ``// current subarray    ``        ``rptr->start = spos;` `        ``// Stores end index of``        ``// current subarray``        ``rptr->end = epos;` `        ``// Update pointer to the first``        ``// element of the array``        ``rptr->a = arr;``        ` `        ` `        ``// creating each thread with``        ``// appropriate parameters``        ``int` `a``        ``= pthread_create(&threads[i], NULL,``                        ``func, (``void``*)(rptr));``                        ` `                        ` `        ``// updating the parameters``        ``// for the next thread``        ``spos = epos + 1;``        ``epos = spos + (N / T) - 1;``        ``if` `(i == T - 2) {``            ``epos = N - 1;``        ``}``    ``}` `    ``// Waiting for threads to finish``    ``for` `(``int` `i = 0; i < T; i++) {``        ``int` `rc``        ``= pthread_join(threads[i], NULL);``    ``}` `    ``// Traverse the map``    ``for` `(``auto` `it: mp) {``                ` `                ` `                                    ` `    ``// If frequency of current``    ``// element is 1                            ``        ``if` `(it.second == 1) {` `            ``// Print the element``            ``cout << it.first << ``" "``;``        ``}``    ``}``}`  `// Drivers Code``int` `main()``{``    ``// initializing the mutex lock``    ``pthread_mutex_init(&lock1, NULL);``    ``int` `T = 3;``    ``int` `arr[] = { 1, 0, 5, 5, 2, 6 };``    ``int` `N = ``sizeof``(arr) / ``sizeof``(arr[0]);``    ``numbers_occuring_once(arr, N, T);``}`
Output:
` `

Time Complexity: O(N * log(N))
Auxiliary Space: O(N)

Note: It is recommended to execute the program in a Linux based system using the following command:

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.  To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

In case you wish to attend live classes with experts, please refer DSA Live Classes for Working Professionals and Competitive Programming Live for Students.

My Personal Notes arrow_drop_up