生产者 - 消费者堆栈行为而不是队列

时间:2014-03-19 09:49:53

标签: c producer-consumer

我使用大小为5的缓冲区编写了一个标准生产者 - 消费者问题的解决方案,并使用空的完整信号量和互斥锁来编写pthreads。我认为一切都按预期工作但只是注意到我正在获得堆栈行为(LIFO)而不是预期的队列(FIFO)行为。我已经搜索过但无法找到任何类似的问题,因为我正按照订单生产和消费。

这是一个家庭作业,所以我不是在寻找代码我只是想知道在哪里寻找错误或者知道为什么行为可能与预期不同。

struct data
{
pthread_mutex_t mutex;  
sem_t full;             
sem_t empty;
};

int bufferCount;        

buffer_item buffer[BUFFER_SIZE];
pthread_t thread;

int insert_item(buffer_item item)
{
  if (bufferCount < BUFFER_SIZE)
  {
    buffer[bufferCount] = item;
    ++bufferCount;
    return 0;
  }
  else
    return -1; //insert failed 
}

int remove_item(buffer_item *item)
{
  if (bufferCount > 0) 
  {
    *item = buffer[bufferCount - 1];
    --bufferCount;
    return 0;
  }
  else
    return -1; //error failed to remove

}

void Initialize (void *param)
{
  struct data *locks = param;

  pthread_mutex_init(&(locks->mutex), NULL);
  sem_init(&(locks->full), 0, 0);
  sem_init(&(locks->empty), 0, BUFFER_SIZE);
  bufferCount = 0;

}

void *producer (void *param)
{
  struct data *locks = param;
  do
  {
    sleep(rand()%5 + 1); //sleep for between 1 and 5 seconds
    buffer_item num = rand();
    sem_wait(&(locks->empty));
    pthread_mutex_lock(&(locks->mutex));
    if (insert_item(num))
    {
      printf("Insert in producer failed\n");
      exit(1);
    }
    else
      printf("Producer produced %d\n", num);
    pthread_mutex_unlock(&(locks->mutex));
    sem_post(&(locks->full));
  }while(1);
}


void *consumer (void *param)
{
  struct data *locks = param;
  do
  {
    sleep(rand()%5 + 1); //sleep for between 1 and 5 seconds
    buffer_item num;
    sem_wait(&(locks->full));
    pthread_mutex_lock(&(locks->mutex));
    if (remove_item(&num))
    {
      printf("Remove in consumer failed\n");
      exit(1);
    }
    else
      printf("Consumer consumed %d\n", num);
    pthread_mutex_unlock(&(locks->mutex));
    sem_post(&(locks->empty));
  }while(1);
}


int main(int argc, char *argv[])
{
  if (argc != 4)
  {
    printf("Incorrect number of arguments should be 4\n");
    exit (1);
  }
  int sleepTime = atoi(argv[1]);  
  int producerThreads = atoi(argv[2]);
  int consumerThreads = atoi(argv[3]);
  struct data *locks = (struct data *) malloc(sizeof(struct data));
  Initialize(locks);

  for (int i =0; i < producerThreads; ++i)
    pthread_create(&thread, NULL, producer, locks);

  for(int i = 0; i < consumerThreads; ++i)
    pthread_create(&thread, NULL, consumer, locks);

  sleep(sleepTime); 
  free (locks);
  return 0;
}

1 个答案:

答案 0 :(得分:1)

您的“错误”在于:*item = buffer[bufferCount - 1];

当你删除一个项目时,你会弹出最远的数组,这也是最后插入的(因此LIFO行为)。你需要弹出第一个(和memcpy / index-keeping来移动缓冲区的开始)。

你做了什么:

begin         <-end  
-------------------
| | | | | | | | |x|
-------------------
                 |
                 -> *item

你想做什么:

begin->         end  
-------------------
|x| | | | | | | | |
-------------------
 |
 -> *item

PS:memcpy缓冲区重新调整数据数组的开头会有性能损失,这就是经常使用circular buffers的原因。