Нить основной с 2 ​​сыновьями нить в цикле х раз продукт и потребитель - PullRequest
0 голосов
/ 04 октября 2018

Я написал программу, в которой главный поток создает два потока сыновей.Каждый ожидает случайное время, затем производит случайное значение между 1 и 6 и помещает значение в переменную randomValue.Другой ожидает и читает глобальную переменную randomValue и печатает переменную. Так что я использовал один семафор, чтобы быть уверенным, что читающий поток всегда будет читать значение, записанное другим потоком.

Я хочу изменить такчто каждый поток не знает x циклов (2,3 ...), так что он может произвести x раз случайное значение и поместить это значение в randomValue, а другой поток прочитает x раз переменную randomValue и напечатаетЭто .Любая идея изменить код приветствуется.Большое спасибо.

#include <time.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <pthread.h>
#include <semaphore.h>

/* variable shared by producer and consumer 
 (producer writes a value between 1 and 6) */

long randomValue = 0;
/**semaphore  **/
sem_t mex;


// function that create a random sleep-time (to induce unpredictability)
static int duration(int min, int max)
{
  static int first_time = 1;

  // Seed the random number generator with the current time
  // of day if we haven't done so yet.
  if (first_time) {
    first_time = 0;
    srand48((int) time(NULL));
  }
  return (int) (min + drand48()*(max - min));
}

/* producer program */
void *producer(void *arg) {
  char statearray[256];

  // Initialize random generator
  // Note that initstate and random are not threadsafe
  initstate(time(NULL), statearray, 256);

   sleep(duration(1,3));
   printf("prod: producing ...\n");
//random value 1 et 6
   randomValue = random();
   randomValue = ((double) randomValue / RAND_MAX)*6+1;
//put the value
   printf("prod: delivering  %ld\n", randomValue);
   sem_post(&mex); 
  pthread_exit(NULL);
}

/* consumer program */
void *consumer(void *arg) {


  sleep(duration(1,5));
  sem_wait(&mex);
  printf("cons: consuming ...\n");
  // 

  printf("cons: received %ld\n", randomValue);


  pthread_exit(NULL);
}

/* main thread */
int main(int argc, char *argv[]) {
  pthread_t tidprod, tidcons;


    if (sem_init(&mex,0,0)  != 0){
    perror("sem_init");
    exit(EXIT_FAILURE);
   }

  if (pthread_create(&tidprod, NULL, producer, NULL) != 0) {
    perror("pthread_create");
  }
  if (pthread_create(&tidcons, NULL, consumer, NULL) != 0) {
    perror("pthread_create");
  }


  if (pthread_join(tidcons, NULL) != 0) {
    perror("pthread_join prod");
  }

  if (pthread_join(tidprod, NULL) != 0) {
    perror("pthread_join prod");
  }

  fflush(stdout);
  pthread_exit(EXIT_SUCCESS);
}

Ответы [ 2 ]

0 голосов
/ 04 октября 2018

Вы можете делать то, что хотите, с помощью нескольких модификаций:

  • Вместо одного семафора используйте два: один семафор, чтобы сообщить потребителю, что число готово, другой, чтобы сообщить производителю, что потребительготов к употреблению.
  • Имеет специальное значение, указывающее потребителю, что производитель больше не будет производить.

Итак, вы можете изменить свой код следующим образом:

Объявление семафоров

/*semaphores  */
/* Set by producer when production is ready */
sem_t mex_prod;
/* Set by consumer when ready to consume */
sem_t mex_cons;

Семафоры init

/* by default, nothing produced */
if (sem_init(&mex_prod,0,0)  != 0){
    perror("sem_init");
    exit(EXIT_FAILURE);
}
/* by default, consumer is not ready */
if (sem_init(&mex_cons,0,0)  != 0){
    perror("sem_init");
    exit(EXIT_FAILURE);
}

функция потока производителя

(я удалил ваш комментарий)

void *producer(void *arg) {
    char statearray[256];
    initstate(time(NULL), statearray, 256);

    /* choose how much to product  */
    int number_of_productions = 2 + random()%5;

    printf("prod: %d to produce\n", number_of_productions );

    /* this loop can be replaced by some for (i = 0; i< num; ++i) loop */
    while(number_of_productions--)
    {
        sleep(duration(1,3));           

        /* wait for consumer to be ready */
        sem_wait(&mex_cons);

        printf("prod: producing ...\n");

        randomValue = random();
        randomValue = ((double) randomValue / RAND_MAX)*6+1;

        printf("prod: delivering  %ld\n", randomValue);
        sem_post(&mex_prod); 
    }

    sem_wait(&mex_cons);

    /* generate a special value to tell the consumer that no new value
       will be given */
    randomValue  = -1;

    sem_post(&mex_prod); 

    pthread_exit(NULL);
}

функция пользовательских потоков

void *consumer(void *arg) {

    /* tell producer that consumer is ready */
    sem_post(&mex_cons);

    /* since we don't know how many value will be generated, we have an
       infinite loop */
    while(1)
    {
        sleep(duration(1,5));
        sem_wait(&mex_prod);
        printf("cons: consuming ...\n");

        printf("cons: received %ld\n", randomValue);

        /* value has been consumed, tell producer we are ready for a new one */
        sem_post(&mex_cons); 

        /* if randomValue is -1, we break the loop since no more value will come */
        if (-1 == randomValue)             
            break;

    }
    pthread_exit(NULL);
}
0 голосов
/ 04 октября 2018

Не совсем понятно, хотите ли вы только отправлять и получать несколько значений.

Для отправки и получения нескольких значений используйте для цикла в производителе и потребителе и массив как randomValue.Если вы хотите создать одно значение и использовать его первым, цикл будет включать в себя "sem_post (& mex);"в продюсере и "sem_wait (& mex);"в петле.В противном случае sem_post () и sem_wait () будут вне цикла.

...