多生产者多消费者队列中的队列覆盖

时间:2018-07-12 19:13:47

标签: multithreading c++11 queue producer-consumer

在下面的多生产者和单消费者固定大小队列实现中,我看到该队列被生产者覆盖。

  

为什么队列被覆盖?

目前,我不是在看代码的性能,而是希望看到所推送的每个项目都已消耗并且没有丢失。

  

如何将其扩展到多产品多消费者?

#include <iostream>
#include <thread>
#include <mutex>
#include <utility>
#include <ctime>
#include <condition_variable>
#include <stdlib.h>
#include <unistd.h>
#include <atomic>

using namespace std;

enum class returncode { QUEUE_EMPTY, QUEUE_FULL,SUCCESS } ;
atomic_long d;

class Queue {
  private:
    long* qdata;
    atomic_size_t length;
    atomic_size_t head;
    atomic_size_t tail ;
    atomic_size_t size;
    std::mutex qmutex;
    std::condition_variable qcond ;

  public:
    Queue(size_t len): length(len)
  {
    qdata=new long[length] ; 
    head=0;
    tail=0;
    size=0;
    srand(time(NULL));
  }

    bool isfull()
    {
      if( size == length )
        return true;

      return false;
    }

    bool isempty()
    {
      if(size == 0)
        return true;

      return false;
    }

    returncode push(long data)
    {
      std::unique_lock<std::mutex> qguard(qmutex);

      if(size == length) //if isfull
        return returncode::QUEUE_FULL ;

      qdata[head]=data;
      head = (head+1) % length; 
      size += 1 ;
      qcond.notify_one();
      qguard.unlock();     //Should the unlock come before notify_one? 
      return returncode::SUCCESS; 
    }

    //Its the users responsibility to check isempty before calling front.
    //Read function
    long front(void)
    {
      std::unique_lock<std::mutex> qguard(qmutex);
      //if isempty
      if( size == 0 )
        return 0;

      long d=qdata[tail];
      return d;
    }

    void pop(void)
    {
      std::thread::id thisthreadid = std::this_thread::get_id();

      std::unique_lock<std::mutex> qguard(qmutex);

      while(size == 0 ) // check condition to be safe against spurious wakes 
      {
        qcond.wait(qguard);// release lock and go join the waiting thread queue 
        return;
      }
      tail =(tail+1) % length;
      size -= 1;

    }
};

void produce(Queue* q)
{
  while(true)
  {
    d++;
    q->push(d) ;
    //sleep(1);
  }
}

void consume(Queue* q)
{
  while(true){
    //usleep(1000);
    cout <<"Consume: Pop " <<  q->front() <<endl;
    q->pop();
  }
}

int main(int argc, char** argv )
{
  Queue q(50);
  d=0;
  int nprods=4;
  int nconsu=1;

  std::thread producers[nprods];
  std::thread consumers[nconsu];

  for (int i=0; i < nprods ; ++i)
    producers[i] = std::thread(produce, &q);

  for (int i=0; i < nconsu ; ++i)
    consumers[i] = std::thread(consume, &q);

  for (int i=0; i<nprods; ++i)
    producers[i].join();

  for (int i=0; i<nconsu; ++i)
    consumers[i].join();

  return 0;
}
  

输出:

Consume: Pop 1
Consume: Pop 2
... Sequential all upto the queue size and then q is over written. 
Consume: Pop 49
Consume: Pop 50
Consume: Pop 51
Consume: Pop 52
Consume: Pop 53
Consume: Pop 54
Consume: Pop 55
Consume: Pop 56
Consume: Pop 64  --> 57 to 63 lost
Consume: Pop 72  --> 65 to 71 lost
Consume: Pop 81
Consume: Pop 89
Consume: Pop 97
Consume: Pop 105

0 个答案:

没有答案