繁体   English   中英

一个生产者,两个消费者对生产者产生的一个“队列”起作用

[英]One producer, two consumers acting on one 'queue' produced by producer

前言:我是多线程编程的新手,对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

在消费者中:

  1. 锁定互斥锁: pthread_mutex_lock(&mMutex1)
  2. 检查向量是否为空,如果是,则向生产者发送信号: pthread_cond_signal(&mEmpty)
  3. 否则将值插入两个新向量之一(取决于哪个线程),然后从原始向量中删除
  4. 解锁互斥锁: pthread_mutex_unlock(&mMutex1)
  5. 返回步骤1

我的程序怎么了? 我不断遇到细分错误或无限循环。

编辑:这是代码:

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);
    }
}

我不确定我是否理解您做事方式的基本原理。 在通常的消费者-提供者习惯用法中,提供者将尽可能多的项目推入通道,仅在通道中空间不足时才等待; 它不会等待清空。 因此,通常的习惯用法是:

提供者(推送一项):

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

您的代码中还有许多其他问题。 其中一些看起来更像是错别字:您应该复制/粘贴实际代码来避免这种情况。 您真正的意思是在推入mGeneratedNumber时读取并弹出mGeneratedValues并检查是否为空吗? (如果您实际上确实有两个不同的队列,那么您将从没有人推送的队列中弹出。)而且,您没有任何循环在等待条件。 您不断迭代期望的元素数量(每次增加计数器,因此您很可能早就应该萌发了)—我看不到无限循环,但是我很容易在pthread_cond_wait中看到无尽的等待。生产者。 我看不到核心转储,但是当其中一个进程终止时(可能是消费者,因为它从不等待任何东西)会发生什么? 如果最终破坏了互斥量或条件变量,则当另一个进程尝试使用它们时,您可能会获得核心转储。

在生产者中,仅当队列不为空时才调用pthread_cond_wait 否则,由于比赛条件,您将永远被封锁。

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.

您可能希望仅在条件满足后才考虑使用互斥锁,例如

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM