0
1つのプロバイダと複数のコンシューマに対して、サイズが制限されたブロックキューを実装しようとしています。消費者が1秒間眠っているときはうまく働いていますが、睡眠がないときはハングアップします。 私は何が間違っていますか?ここC++ stdキューを使用したブロックキュー
は私のコードです:ここでは
#include <iostream>
#include <stdlib.h>
#include <unistd.h>
#include <thread>
#include <queue>
#include <mutex>
#include <condition_variable>
using namespace std;
template <class T> class BlockingQueue: public queue<T> {
public:
BlockingQueue() {
queue<T>();
}
BlockingQueue(int size) {
maxSize = size;
queue<T>();
}
void push(T item) {
unique_lock<std::mutex> wlck(writerMutex);
while(Full())
isFull.wait(wlck);
queue<T>::push(item);
if(notEmpty())
isEmpty.notify_one();
}
bool notEmpty() {
return !queue<T>::empty();
}
bool Full(){
return queue<T>::size() >= maxSize;
}
T pop() {
unique_lock<std::mutex> lck(readerMutex);
popMutex.lock();
while(queue<T>::empty()) {
isEmpty.wait(lck);
}
T value = queue<T>::front();
queue<T>::pop();
if(!Full())
isFull.notify_all();
popMutex.unlock();
return value;
}
private:
int maxSize;
std::mutex readerMutex;
std::mutex popMutex;
std::mutex writerMutex;
condition_variable isFull;
condition_variable isEmpty;
};
void runProvider(BlockingQueue<int>* Q) {
int number=0;
while(1) {
Q->push(number);
cout<<"provide "<<number<<endl;
number++;
}
}
void runConsumer(int n,BlockingQueue<int>* Q) {
int number;
while(1) {
number = Q->pop();
cout<<"consume#"<<n<<": "<<number<<endl;
}
}
int main(int argc, char** argv) {
BlockingQueue<int> *Queue = new BlockingQueue<int>(10);
cout<<"starting provider"<<endl;
std:thread provider(runProvider, Queue);
sleep(1);
cout<<"starting consumer"<<endl;
std::thread consumer1(runConsumer, 1,Queue);
std::thread consumer2(runConsumer, 2,Queue);
provider.join();
delete(Queue);
return 0;
}
単一のミューテックスが十分でなければなりません。あなたはwronトラックにいます。 –
また、キューに新しい要素を追加した後、 'notEmpty()'はtrueになることが保証されています。したがって 'if(notEmpty())'は時間の無駄です。要素をポップした後の 'if(!Full())'のことです。さらに、コンストラクタ本体の 'queue()'はまったく役に立たず、全く何も実行しません。 –
1つのミューテックスを使用すると、キューがいっぱいになってキューが空のときにライターがロックされます。それは動作しません。 キューがいっぱいのときは書き込みブロッキングが必要で、キューが空のときは読み取りブロッキングが必要です。 – nubee