dimanche 6 novembre 2022

The producer_consumer multithreading problem with locks and condition_variable results in a hang or a deadlock

Question 1 : I'm trying to implement sample code for Producer_Consumer problem, where I'm using one counter and queue to share resources between them. Unfortunately, this implementation leads to a hang/deadlock. Looks like the thread isn't doing spurious wakeups during consumption.

ProducerConsumer output

Question 2 : With addition to the above if I don't use static keyword for mutex and condition_variable, it gives compilation error stating : -

Error C2661 'std::tuple<void (__cdecl ProducerAndConsumer:: )(void),ProducerAndConsumer>::tuple': no overloaded function takes 2 arguments C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\include\memory 3382*

Why do I need to declare them as static ??

I tried with the below code :

#include <thread>
#include <condition_variable>
#include <mutex>
#include <queue>
#include <random>
using namespace std;

class ProducerAndConsumer
{
    static condition_variable cond;
    static mutex mu;
    queue<int> q;
    int QSIZE { 10 };
    int count = 20;

public:

    void Producer()
    {
        while (count)
        {
            unique_lock<mutex> locker(mu);
            cond.wait(locker, [&]() {return q.size()< QSIZE; });
            int item = count--;
            cout << "Producer : " << item << endl;
            //cout << "size" << q.size() << endl;
            q.push(item);
            locker.unlock();
            cond.notify_all();
        }
    }

    void Consumer()
    {
        int item = 0;
        while (item != 1)
        {
            unique_lock<mutex> locker(mu);
            cond.wait(locker, [&]() {return !q.empty(); });
            item = q.front();
            cout << "Consumer : " << item << endl; 
            q.pop();
            locker.unlock();
            cond.notify_all();
        }
    }
    
};

condition_variable ProducerAndConsumer::cond;
mutex ProducerAndConsumer::mu;

int main()
{
    ProducerAndConsumer p;
    
    std::thread t1(&ProducerAndConsumer::Producer, p);
    std::thread t2(&ProducerAndConsumer::Consumer, p);
    t1.join();
    t2.join();

    std::cout << "Hello World" << std::endl;
    return true;
}

Aucun commentaire:

Enregistrer un commentaire