Producer Consumer Problem



  • hi, brauche ich beim folgenden beispiel: Producer, Consumer Problem noch einen weiteren lock? wie funktioniert cv.wait(l, [this](){ return !produced; } ); // 1 genau?

    #include <iostream>
    #include <thread>
    #include <mutex>
    #include <condition_variable>
    using namespace std;
    
    class ProducerConsumer {
    private:
        int value; // 1
        bool produced; // 2
        mutex m;
    	condition_variable cv;
    
    public:
    	ProducerConsumer(): value(-1), produced(false) {}
    
    	void producer(unsigned int count) {
            for(int i = count; i >= 0; --i) {
                unique_lock<mutex> l(m);
                cv.wait(l, [this](){ return !produced; } ); // 1
    
                cout << "Producer sets value to " << i << endl;
                value = i;
                produced = true;
                cv.notify_one(); // 2
            }
        }
    
    	void consumer() {
    	    do {
                unique_lock<mutex> l(m);
                cv.wait(l, [this](){ return produced; } );
    
                cout << "Consumer now is in control: " << value << endl;
                produced = false;
                cv.notify_one();
            } while(value);
    	}
    };
    
    int main() {
    	// your code goes here
    
    	ProducerConsumer p;
    	thread t1(&ProducerConsumer::consumer, &p);
    	thread t2(&ProducerConsumer::producer, &p, 2);
    
    	t1.join();
    	t2.join();
    
    	return 0;
    }
    


  • warum beenden thread1 und thread2 nicht wenn ich 2 consumer hinzufuege?

    #include <iostream> 
    #include <thread> 
    #include <mutex> 
    #include <condition_variable> 
    using namespace std;
    
    /* Question:
    
    */
    
    class ProducerConsumer {
    private:
    	int value; // 1 
    	bool produced; // 2 
    	mutex m;
    	condition_variable cv;	
    
    public:
    	ProducerConsumer() : value(-1), produced(false) {}
    
    	void producer(unsigned int count) {
    		for (int i = count; i >= 0; --i) {
    			unique_lock<mutex> l(m);
    			cv.wait(l, [this](){ return !produced; }); // 1 
    
    			cout << "Producer sets value to " << i << endl;
    
    			value = i;
    			produced = true;
    			cv.notify_one(); // 2 
    		}
    	}
    
    	void consumer(unsigned int thread_id) {
    		do {
    			unique_lock<mutex> l(m);
    			cv.wait(l, [this](){ return produced; });
    
    			cout << "Consumer thread " << thread_id << "...now is in control: " << value << endl;
    			produced = false;
    			cv.notify_one();
    		} while (value);
    
    		cout << thread_id << endl;
    	}
    };
    
    int main() {
    	// your code goes here 
    
    	ProducerConsumer p;
    	thread t1(&ProducerConsumer::consumer, &p, 1);
    	thread t2(&ProducerConsumer::consumer, &p, 2);
    	thread t3(&ProducerConsumer::producer, &p, 3);
    
    	t3.join();
    	t1.join();
    	t2.join();
    
    	return 0;
    }
    


  • Any idea?



  • problem gefunden, ein consumer thread musste im wait unendlich lange warten...
    warum bekommen jetzt manchmal 2 consumer threads gleichzeitig access?

    #include <iostream> 
    #include <thread> 
    #include <mutex> 
    #include <condition_variable> 
    using namespace std;
    
    /* Question:
    
    */
    
    class ProducerConsumer {
    private:
    	int value; // 1 
    	bool produced; // 2 
    	mutex lock;
    	mutex m;
    	condition_variable cv;
    
    public:
    	ProducerConsumer() : value(-1), produced(false) {}
    
    	void producer(unsigned int count) {
    		for (int i = count; i >= 0; --i) {
    			{
    				unique_lock<mutex> l(lock);
    				cv.wait(l, [this](){ return !produced; }); // 1
    			}
    
    			{
    				unique_lock<mutex> l(m);
    				cout << "Producer sets value to " << i << endl;
    			}
    
    			value = i;
    			produced = true;
    			cv.notify_one(); // 2 
    		}
    	}
    
    	void consumer(unsigned int thread_id) {
    		do {
    			bool exit_loop = false;
    
    			{
    				unique_lock<mutex> l(lock);
    
    				if (!cv.wait_for(l, std::chrono::milliseconds(500), [this](){ return produced; })) {
    					std::cerr << "Thread " << thread_id << " finished waiting" << endl;
    					exit_loop = true;
    					break;
    				}
    			}
    
    			if (exit_loop) {
    				break;
    			}
    
    			{
    				unique_lock<mutex> l(m);
    				cout << "Consumer thread " << thread_id << "...now is in control: " << value << endl;
    			}
    
    			produced = false;
    			cv.notify_one();
    
    			std::this_thread::sleep_for(std::chrono::milliseconds(10));
    		} while (value);
    	}
    };
    
    int main() {
    	// your code goes here 
    
    	ProducerConsumer p;
    	thread consumer_thread1(&ProducerConsumer::consumer, &p, 1);
    	thread consumer_thread2(&ProducerConsumer::consumer, &p, 2);
    	thread producer_thread(&ProducerConsumer::producer, &p, 10);
    
    	producer_thread.join();
    	consumer_thread1.join();
    	consumer_thread2.join();
    
    	cout << "\nThreads successfully completed..." << endl;
    
    	return 0;
    }
    


  • beispiel:

    Producer sets value to 10
    Consumer thread 2...now is in control: 10
    Producer sets value to 9
    Consumer thread 1...now is in control: 9
    Consumer thread 2...now is in control: 9
    Producer sets value to 8
    Consumer thread 1...now is in control: 8
    Consumer thread 2...now is in control: 8
    Producer sets value to 7
    Consumer thread 1...now is in control: 7
    Producer sets value to 6
    Consumer thread 2...now is in control: 6
    Producer sets value to 5
    Consumer thread 1...now is in control: 5
    Producer sets value to 4
    Consumer thread 2...now is in control: 4
    Producer sets value to 3
    Consumer thread 1...now is in control: 3
    Producer sets value to 2
    Consumer thread 2...now is in control: 2
    Producer sets value to 1
    Consumer thread 1...now is in control: 1
    Producer sets value to 0
    Consumer thread 2...now is in control: 0
    
    Threads successfully completed...
    


  • algoman1 schrieb:

    ...warum bekommen jetzt manchmal 2 consumer threads gleichzeitig access?

    Der unique_lock (Z.45) ist nur in dem scope in dem er definiert ist wirksam (Z.45 - 52). Der zweite lock (m) ist überflüssig, doppelt hält nicht besser 😉


Anmelden zum Antworten