📜  在三个线程之间共享一个队列

📅  最后修改于: 2022-05-13 01:57:01.069000             🧑  作者: Mango

在三个线程之间共享一个队列

根据给定的规范在三个线程 A、B、C 之间共享一个队列:

  • 线程 A 生成随机整数并将它们推送到共享队列中。
  • 线程 B 和 C 相互竞争以从队列中获取一个整数。
  • 线程 B 和 C 计算它们从队列中获取的整数的总和。
  • 比较 B 和 C 计算的总和。最大的是赢家。

先决条件:-多线程

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程。

方法:-创建一个在所有三个线程之间共享的全局队列。首先创建所有三个线程并调用与它们关联的相应函数。

  • producerFun生成随机数并将它们推入队列
  • add_B函数复制线程 B 并消耗特定数量的队列。
  • add_C函数复制线程 C 并消耗特定数量的队列。

注意:-每个函数中都有互斥锁以避免任何竞争条件。

C++
// CPP program to demonstrate the given task
#include 
#include 
#include 
#include 
 
#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 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

注意:每次代码运行时输出都会不同。