Как сделать так, чтобы потоки и производителя, и потребителя работали бесконечно и один за другим? - PullRequest
0 голосов
/ 11 апреля 2019

Как сделать так, чтобы функции как производителя, так и потребителя работали бесконечно и одна за другой? Например: сначала я хочу, чтобы пользователь ввел массив, а затем функция-потребитель печатает введенный массив, а затем снова просит пользователя ввести массив.

/*  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 голосов
/ 11 апреля 2019

В вашем коде есть несколько серьезных проблем.

  1. Мьютекс может быть разблокирован потоком, только если поток заблокировал его ранее.В вашем коде мьютекс заблокирован вне функции цикла и разблокирован внутри цикла.Это даст неопределенное поведение.
  2. Функция потребителя выполняет signal_wait () перед входом в цикл.Я думаю, вы предположили, что потоки производителя и потребителя запускаются почти одновременно, и производитель не будет сигнализировать, пока потребитель не заблокирует мьютекс.Это не верно. Вы должны предполагать, что потоки планируются в случайном порядке и обрабатывать все возможные случаи.
  3. Вы не уведомляете производителя, когда потребитель полностью использует данные.Не существует механизма сигнализации от потребителя к производителю.
  4. Вы уведомляете потребителя, когда производитель полностью произвел данные.Но потребитель не ждет снаружи пока цикл.Это означает, что только один раз он может получить уведомление.
  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); 
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...