Sharing a queue among three threads

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.

filter_none

edit
close

play_arrow

link
brightness_4
code

// 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;
  
// Fuction 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 exectuing, 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 consmed 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 exectuing, 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 consmed 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 exectuing, 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;
}

chevron_right


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

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.




Article Tags :
Practice Tags :


Be the First to upvote.


Please write to us at contribute@geeksforgeeks.org to report any issue with the above content.