一个生产者,两个消费者在生产者生产的一个“队列”上行事

时间:2012-03-22 13:02:30

标签: c++ multithreading pthreads producer-consumer

前言:我是多线程编程的新手,而且对C ++有点生疏。我的要求是使用一个互斥锁,以及两个条件mNotEmptymEmpty。我还必须以下面提到的方式创建和填充向量。

我有一个生产者线程创建一个大小为n*2的随机数的向量,两个消费者将这些值插入到两个大小为n的单独向量中。

我在制片人中做以下事情:

  1. 锁定互斥锁:pthread_mutex_lock(&mMutex1)
  2. 等待消费者说向量为空:pthread_cond_wait(&mEmpty,&mMutex1)
  3. 将值推回向量
  4. 告知消费者该向量不再为空:pthread_cond_signal(&mNotEmpty)
  5. 解锁互斥锁:pthread_mutex_unlock(&mMutex1)
  6. 返回第1步
  7. 在消费者中:

    1. 锁定互斥锁:pthread_mutex_lock(&mMutex1)
    2. 检查矢量是否为空,如果是,则告知生产者:pthread_cond_signal(&mEmpty)
    3. 否则将值插入两个新向量之一(取决于哪个线程)并从原始向量中删除
    4. 解锁互斥锁:pthread_mutex_unlock(&mMutex1)
    5. 返回第1步
    6. 我的流程出了什么问题?我不断得到分段错误或无限循环。

      编辑:这是代码:

      void Producer()
      {
          srand(time(NULL));
          for(unsigned int i = 0; i < mTotalNumberOfValues; i++){
              pthread_mutex_lock(&mMutex1);
      
              pthread_cond_wait(&mEmpty,&mMutex1);
              mGeneratedNumber.push_back((rand() % 100) + 1);
      
              pthread_cond_signal(&mNotEmpty);
              pthread_mutex_unlock(&mMutex1);
          }
      }
      
      void Consumer(const unsigned int index)
      {
          for(unsigned int i = 0; i < mNumberOfValuesPerVector; i++){
              pthread_mutex_lock(&mMutex1);
              if(mGeneratedNumber.empty()){
                  pthread_cond_signal(&mEmpty);
              }else{
                  mThreadVector.at(index).push_back[mGeneratedNumber.at(0)];
                  mGeneratedNumber.pop_back();
              }
      
              pthread_mutex_unlock(&mMutex1);
          }
      }
      

4 个答案:

答案 0 :(得分:4)

我不确定我理解你所做法背后的理由 的东西。在通常的消费者提供者习语中,提供者推动 许多项目尽可能进入频道,只有等待才有 渠道空间不足;它不等待空。所以 通常的习惯用语是:

提供者(推送一个项目):

pthread_mutex_lock( &mutex );
while ( ! spaceAvailable() ) {
    pthread_cond_wait( &spaceAvailableCondition, &mutex );
}
pushTheItem();
pthread_cond_signal( &itemAvailableCondition );
pthread_mutex_unlock( &mutex );

并且在消费者方面,获得一个项目:

pthread_mutex_lock( &mutex );
while ( ! itemAvailable() ) {
    pthread_cond_wait( &itemAvailableCondition, &mutex );
}
getTheItem();
pthread_cond_signal( &spaceAvailableCondition );
pthread_mutex_unlock( &mutex );

请注意,对于每个条件,一侧发出信号,另一侧发出等待。 (一世 在你的消费者中看不到任何等待。)如果有不止一个 在任何一方的过程中,我建议使用pthread_cond_broadcast, 而不是pthread_cond_signal

您的代码中还有许多其他问题。其中一些看起来更多 像拼写错误:你应该复制/粘贴实际代码以避免这种情况。你呢 当你进入时,真正意思是阅读和弹出mGeneratedValues mGeneratedNumber,并检查是否为空? (如果你真的 有两个不同的队列,然后你从没有的队列中弹出 一个人推了。)而你没有任何循环等待 条件;你不断迭代你的元素数量 期待(每次递增计数器,所以你很可能 早在你应该之前就已经知道了) - 我看不到无限循环, 但我很容易在pthread_cond_wait中看到无休止的等待 制片人。我没有看到核心转储,但是当发生核心转储时会发生什么 进程终止(可能是消费者,因为它永远不会 等待任何事情);如果它最终破坏了互斥锁或条件 变量,你可以在另一个进程尝试时获得核心转储 使用它们。

答案 1 :(得分:1)

在生产者中,仅当队列不为空时才调用pthread_cond_wait。否则,由于竞争条件,你会永远被封锁。

答案 2 :(得分:0)

您可能只想在条件满足后考虑使用互斥锁,例如

producer()
{
    while true
    {
        waitForEmpty();
        takeMutex();
        produce();
        releaseMutex();
    }
}

consumer()
{
    while true
    {
        waitForNotEmpty();
        takeMutex();
        consume();
        releaseMutex();
    }
}

答案 3 :(得分:0)

Here is a solution to a similar problem like you. In this program producer produces a no and writes it to a array(buffer) and a maintains a file then update a status(status array) about it, while on getting data in the array(buffer) consumers start to consume(read and write to their file) and update a status that it has consumed. when producer looks that both the consumer has consumed the data it overrides the data with a new value and goes on. for convenience here i have restricted the code to run for 2000 nos.

// Producer-consumer //

#include <iostream>
#include <fstream>
#include <pthread.h>

#define MAX 100

using namespace std;

int dataCount = 2000;

int buffer_g[100];
int status_g[100];

void *producerFun(void *);
void *consumerFun1(void *);
void *consumerFun2(void *);

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

pthread_cond_t dataNotProduced = PTHREAD_COND_INITIALIZER;
pthread_cond_t dataNotConsumed = PTHREAD_COND_INITIALIZER;

int main()
{

  for(int i = 0; i < MAX; i++)
    status_g[i] = 0;

  pthread_t producerThread, consumerThread1, consumerThread2;

  int retProducer = pthread_create(&producerThread, NULL, producerFun, NULL);
  int retConsumer1 = pthread_create(&consumerThread1, NULL, consumerFun1, NULL);
  int retConsumer2 = pthread_create(&consumerThread2, NULL, consumerFun2, NULL);

  pthread_join(producerThread, NULL);
  pthread_join(consumerThread1, NULL);
  pthread_join(consumerThread2, NULL);

  return 0;

}

void *producerFun(void *)
{
    //file to write produced data by producer
    const char *producerFileName = "producer.txt";
    ofstream producerFile(producerFileName);
    int index = 0, producerCount = 0;

    while(1)
    {
      pthread_mutex_lock(&mutex);

      if(index == MAX)
      {
        index = 0;
      }
      if(status_g[index] == 0)
      {

        static int data = 0;
        data++;

        cout << "Produced:  " << data << endl;

        buffer_g[index] = data;

        producerFile << data << endl;

        status_g[index] = 5;

        index ++;
        producerCount ++;

        pthread_cond_broadcast(&dataNotProduced);
      }
      else
      {
        cout << ">> Producer is in wait.." << endl;
        pthread_cond_wait(&dataNotConsumed, &mutex);
      }
      pthread_mutex_unlock(&mutex);

      if(producerCount == dataCount)
      {
        producerFile.close();
        return NULL;
      }
    }
}

void *consumerFun1(void *)
{
  const char *consumerFileName = "consumer1.txt";
  ofstream consumerFile(consumerFileName);
  int index = 0, consumerCount = 0;

  while(1)
  {
    pthread_mutex_lock(&mutex);
    if(index == MAX)
    {
      index = 0;
    }

    if(status_g[index] != 0 && status_g[index] != 2)
    {
      int data = buffer_g[index];

      cout << "Cosumer1 consumed: " << data << endl;
      consumerFile << data << endl;

      status_g[index] -= 3;

      index ++;
      consumerCount ++;

      pthread_cond_signal(&dataNotConsumed);
    }
    else
    {
      cout << "Consumer1 is in wait.." << endl;
      pthread_cond_wait(&dataNotProduced, &mutex);
    }
      pthread_mutex_unlock(&mutex);
    if(consumerCount == dataCount)
    {
      consumerFile.close();
      return NULL;
    }
  }
}

void *consumerFun2(void *)
{
  const char *consumerFileName = "consumer2.txt";
  ofstream consumerFile(consumerFileName);
  int index = 0, consumerCount = 0;

  while(1)
  {
    pthread_mutex_lock(&mutex);
    if(index == MAX)
    {
      index = 0;
    }

    if(status_g[index] != 0 && status_g[index] != 3)
    {


      int data = buffer_g[index];
      cout << "Consumer2 consumed: " << data << endl;
      consumerFile << data << endl;

      status_g[index] -= 2;

      index ++;
      consumerCount ++;

      pthread_cond_signal(&dataNotConsumed);
    }
    else
    {
      cout << ">> Consumer2 is in wait.." << endl;
      pthread_cond_wait(&dataNotProduced, &mutex);
    }
    pthread_mutex_unlock(&mutex);

    if(consumerCount == dataCount)
    {
      consumerFile.close();
      return NULL;
    }
  }
} 

Here is only one problem that producer in not independent to produce, that is it needs to take lock on the whole array(buffer) before it produces new data, and if the mutex is locked by consumer it waits for that and vice versa, i am trying to look for it.
相关问题