Skip to content
Related Articles

Related Articles

Sharing a queue among three threads

Improve Article
Save Article
  • Last Updated : 05 Aug, 2022
Improve Article
Save Article

Share a queue among three threads A, B, C as per given norms : 

  • Thread A generates random integers and pushes them into a shared queue.
  • Threads B and C compete with each other to grab an integer from the queue.
  • The threads B and C compute the sum of integers that they have grabbed from the queue.
  • Compare the sums as computed by B and C. The greatest is the winner.

Prerequisite :- Multithreading

Approach:- Create a global queue which is shared among all three threads. First create all three threads and call the respective functions associated with them. 

  • producerFun generates random numbers and push them into queue
  • add_B function replicates thread B and consumes the queue for certain numbers.
  • add_C function replicates thread C and consumes the queue for certain numbers.

Note :- There is mutex lock in every function to avoid any race condition. 

Implementation:

C++




// CPP program to demonstrate the given task
#include <iostream>
#include <pthread.h>
#include <queue>
#include <stdlib.h>
 
#define MAX 10
 
using namespace std;
 
// Declaring global variables
int sum_B = 0, sum_C = 0;
int consumerCount1 = 0;
int consumerCount2 = 0;
 
// Shared queue
queue<int> Q;
 
// Function declaration of all required functions
void* producerFun(void*);
void* add_B(void*);
void* add_C(void*);
 
// Getting the mutex
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
 
pthread_cond_t dataNotProduced =
                    PTHREAD_COND_INITIALIZER;
pthread_cond_t dataNotConsumed =
                    PTHREAD_COND_INITIALIZER;
 
// Function to generate random numbers and
// push them into queue using thread A
 
void* producerFun(void*)
{
    static int producerCount = 0;
     
    // Initialising the seed
    srand(time(NULL));
     
    while (1) {
        // Getting the lock on queue using mutex
        pthread_mutex_lock(&mutex);
 
        if (Q.size() < MAX && producerCount < MAX)
        {
             
            // Getting the random number
            int num = rand() % 10 + 1;
            cout << "Produced:  " << num << endl;
 
            // Pushing the number into queue
            Q.push(num);
 
            producerCount++;
 
            pthread_cond_broadcast(&dataNotProduced);
        }
 
        // If queue is full, release the lock and return
        else if (producerCount == MAX) {
            pthread_mutex_unlock(&mutex);
            return NULL;
        }
 
        // If some other thread is executing, wait
        else {
            cout << ">> Producer is in wait.." << endl;
            pthread_cond_wait(&dataNotConsumed, &mutex);
        }
 
        // Get the mutex unlocked
        pthread_mutex_unlock(&mutex);
    }
}
 
// Function definition for consumer thread B
void* add_B(void*)
{
 
    while (1) {
 
        // Getting the lock on queue using mutex
        pthread_mutex_lock(&mutex);
 
        // Pop only when queue has at least 1 element
        if (Q.size() > 0) {
            // Get the data from the front of queue
            int data = Q.front();
 
            cout << "B thread consumed: " << data << endl;
 
            // Add the data to the integer variable
            // associated with thread B
            sum_B += data;
 
            // Pop the consumed data from queue
            Q.pop();
 
            consumerCount1++;
 
            pthread_cond_signal(&dataNotConsumed);
        }
 
        // Check if consumed numbers from both threads
        // has reached to MAX value
        else if (consumerCount2 + consumerCount1 == MAX) {
            pthread_mutex_unlock(&mutex);
            return NULL;
        }
 
        // If some other thread is executing, wait
        else {
            cout << "B is in wait.." << endl;
            pthread_cond_wait(&dataNotProduced, &mutex);
        }
 
        // Get the mutex unlocked
        pthread_mutex_unlock(&mutex);
    }
}
 
// Function definition for consumer thread C
void* add_C(void*)
{
 
    while (1) {
 
        // Getting the lock on queue using mutex
        pthread_mutex_lock(&mutex);
 
        // Pop only when queue has at least 1 element
        if (Q.size() > 0) {
 
            // Get the data from the front of queue
            int data = Q.front();
            cout << "C thread consumed: " << data << endl;
 
            // Add the data to the integer variable
            // associated with thread B
            sum_C += data;
 
            // Pop the consumed data from queue
            Q.pop();
            consumerCount2++;
 
            pthread_cond_signal(&dataNotConsumed);
        }
 
        // Check if consumed numbers from both threads
        // has reached to MAX value
        else if (consumerCount2 + consumerCount1 == MAX)
        {
            pthread_mutex_unlock(&mutex);
            return NULL;
        }
 
        // If some other thread is executing, wait
        else {
            cout << ">> C is in wait.." << endl;
            // Wait on a condition
            pthread_cond_wait(&dataNotProduced, &mutex);
        }
 
        // Get the mutex unlocked
        pthread_mutex_unlock(&mutex);
    }
}
 
// Driver code
int main()
{
    // Declaring integers used to
    // identify the thread in the system
    pthread_t producerThread, consumerThread1, consumerThread2;
 
    // Function to create a threads
    // (pthread_create() takes 4 arguments)
    int retProducer = pthread_create(&producerThread,
                      NULL, producerFun, NULL);
    int retConsumer1 = pthread_create(&consumerThread1,
                       NULL, *add_B, NULL);
    int retConsumer2 = pthread_create(&consumerThread2,
                       NULL, *add_C, NULL);
 
    // pthread_join suspends execution of the calling
    // thread until the target thread terminates
    if (!retProducer)
        pthread_join(producerThread, NULL);
    if (!retConsumer1)
        pthread_join(consumerThread1, NULL);
    if (!retConsumer2)
        pthread_join(consumerThread2, NULL);
 
    // Checking for the final value of thread
    if (sum_C > sum_B)
        cout << "Winner is  Thread C" << endl;
    else if (sum_C < sum_B)
        cout << "Winner is  Thread B" << endl;
    else
        cout << "Both has same score" << endl;
     
    return 0;
}

OUTPUT:

B is in wait..
Produced:  10
Produced:  1
Produced:  6
Produced:  6
Produced:  4
C thread consumed: 10
C thread consumed: 1
C thread consumed: 6
C thread consumed: 6
Produced:  1
Produced:  9
Produced:  9
Produced:  6
C thread consumed: 4
C thread consumed: 1
C thread consumed: 9
C thread consumed: 9
C thread consumed: 6
>> C is in wait..
Produced:  5
C thread consumed: 5
Winner is  Thread C

Note : Output will be different everytime code runs.


My Personal Notes arrow_drop_up
Related Articles

Start Your Coding Journey Now!