如何确保生产者线程和消费者线程都无限运行并且一个接一个地运行?

时间:2019-04-11 10:53:50

标签: c linux pthreads

如何确保Producer和Consumer函数都无限运行并且又一个又一个地运行?例如:首先,我希望用户输入数组,然后消费者函数将打印输入的数组,然后再次要求用户输入数组。

/*  Headers  */


pthread_mutex_t mutex;
pthread_cond_t cond,cond1;
void *producer(void *arg);
void *consumer(void *arg);
static int n;
int consumerFlag[100];

void *producer(void *arg) 
{

  pthread_mutex_lock(&mutex);        

  while(1)
    {
      printf("\n Enter no of terms");
      scanf("%d",&n);
      int i; 
      printf("\n Enter consumer flag array");
      for (i = 0; i < n; i++) 
        {
      scanf(" %d",&consumerFlag[i]);
      pthread_mutex_unlock(&mutex);           
        }
      pthread_cond_signal(&cond);    
      usleep(1000);
    }


}


void *consumer(void *arg) 
{
  int i;
  pthread_mutex_lock(&mutex);
  pthread_cond_wait(&cond, &mutex); 
  printf("\nConsumer Function"); 
  while(1)
    {

      printf("\nConsumer thread waiting"); 

      for (i = 0; i < n; i++) 
        {    
          printf("\nConsumerFlag %d = %d", i, consumerFlag[i]); 
          pthread_mutex_unlock(&mutex);         

        }          

    }

}

int main()
{
  int i=0;
  pthread_mutex_init(&mutex,0);
  pthread_cond_init(&cond,0);   
  pthread_t pThread, cThread;
  pthread_create(&pThread, 0, producer, 0);
  pthread_create(&cThread, 0, consumer,0);   
  pthread_join(pThread,NULL);
  pthread_join(cThread, NULL);
  pthread_mutex_destroy(&mutex);
  pthread_cond_destroy(&cond);
  return 0;
}

首先,我希望用户输入数组,然后使用者函数打印输入的数组,然后再次要求用户输入数组。

1 个答案:

答案 0 :(得分:0)

您的代码中很少有主要问题。

  1. 仅当线程已锁定互斥锁时,该互斥锁才能被该线程解锁。在您的代码中,互斥锁在循环功能之外被锁定,而在循环内部被解锁。它将给出未定义的行为。
  2. 在进入循环之前,消费者函数正在执行signal_wait()。我认为您已经假设生产者线程和使用者线程几乎同时启动,并且使用者在锁定互斥对象之前不会发出信号。错了您应该假定线程是按随机顺序安排的并处理所有可能的情况。
  3. 您没有在使用者完全使用数据时通知生产者。没有从消费者到生产者的信号传导机制。
  4. 您要在生产者完全生产数据时通知消费者。但是用户不在while循环之外等待。这意味着,只有一次它可以得到通知。
  5. 在生产者中,condition_signal在解锁互斥锁之后,这是错误的。信号应在互斥锁锁定的情况下调用。

因此,在生产者中,您需要产生数据,将信号发送给消费者并等待消费者确认数据已被消耗。您需要另外设置一个标志,以考虑生产者线程在考虑消费者线程之前获得锁定的情况。在这种情况下,生产者发送信号时,消费者不会进入while循环。因此,消费者无法捕捉到信号。

void *producer(void *arg) 
{     
    pthread_mutex_lock(&mutex);        

    while(1)
    {
        printf("\n Enter no of terms");
        scanf("%d",&n);
        int i; 
        printf("\n Enter consumer flag array");
        for (i = 0; i < n; i++) 
        {
            scanf(" %d",&consumerFlag[i]);
            //pthread_mutex_unlock(&mutex);  //Should not be unlocked in loop         
        }
        data_produced_flag = 1; //A flag to indicate data is ready. Should be initialized to 0 before thread creation. It is required if producer produces before consumer thread goes to pthread_cond_wait()
        pthread_cond_signal(&cond_producer); //Should send signal with mutex locked
        //usleep(1000); //Not required as it is going to wait for signal from consumer

        pthread_cond_wait(&cond_consumer, &mutex); //Wait for confirmation that data is consumed
    }
    pthread_mutex_unlock(&mutex); 
}

在使用者功能中,应检查是否已生成数据。如果未生产,请等待生产者发出的信号。如果有可用数据,请消耗并通知生产者以获取新数据。

void *consumer(void *arg) 
{
    int i;
    pthread_mutex_lock(&mutex);
    //pthread_cond_wait(&cond, &mutex);  //Wait inside loop
    printf("\nConsumer Function"); 
    while(1)
    {
        if(0 == data_produced_flag) 
        {
            printf("\nConsumer thread waiting"); 
            pthread_cond_wait(&cond_producer, &mutex); //Wait for signal from producer
        }
        //else
        //{
            //Data is already produced. No need to wait.
        //}

        //Data is available for consumption
        for (i = 0; i < n; i++) 
        {    
            printf("\nConsumerFlag %d = %d", i, consumerFlag[i]); 
            //pthread_mutex_unlock(&mutex);    //We are in the process of consumption. Don't unlock mutex.
        }
        data_produced_flag = 0; //Reset the flag. Ready for new data.
        pthread_cond_signal(&cond_consumer); //Indicate that data is consumed
    }
    pthread_mutex_unlock(&mutex); 
}