它不应该是线程阻塞

时间:2016-04-03 20:35:03

标签: c multithreading producer-consumer

我正在尝试创建一个消费者生产者程序,其中消费者线程生产者编号填充数组,而消费者线程打印填充数组的数字。目前,我可以填充数组并在消费者/生产者线程之间来回传递数据,但我希望生产者创建数字的速度快于消费者处理它们的速度。

此刻,每1秒生成一个数字,每3个消耗一个数字。在消耗一个数字之前应生成两个数字,但我的生产者线程正在等待它生成的数字被消耗。

我试过移动互斥锁和解锁,以及信号,但我还没有开始工作。以下代码生成以下输出:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <pthread.h>
#include <unistd.h>

struct Data {
  int num;
  int wait_time;
}; 


pthread_mutex_t the_mutex;
pthread_cond_t condc, condp;
//int count = 0;
struct Data buffer[32];


void* producer(void *ptr) {
  int i, w;             /* counter and random wait time */
  struct Data data;
  int count = 0;

  while(1) {
    //w = rand() % 5 + 3;
    w = 1;
    sleep(w);               /* Wait between 3 and 7 seconds */

    data.num = rand() % 1000;       /* Create random number to pass */
    //data.wait_time = rand() % 8 + 2;
    data.wait_time = 3;

    pthread_mutex_lock(&the_mutex); /* lock the buffer */

    while (buffer[count].num != 0) {        /* while full */
      //pthread_cond_signal(&condc);
      pthread_cond_wait(&condp, &the_mutex);
    }

    //pthread_mutex_lock(&the_mutex);   /* lock the buffer */
    buffer[count] = data;

    pthread_cond_signal(&condc);    /* signal consumer */
    pthread_mutex_unlock(&the_mutex);

    printf("Produced %i and slept for %i seconds\n", buffer[count].num, w);

    if (count != 31){
      count += 1;
      //printf("Producer count: %i\n", count);
    }
    else
      count = 0;

    //pthread_cond_signal(&condc);  /* signal consumer */
    //pthread_mutex_unlock(&the_mutex); /* unlock */
  }
  pthread_exit(0);
}


void* consumer(void *ptr) {
  int i;
  int count = 0;

  //for(i = 1; i <= MAX; i++) {
  while(1) {   
     pthread_mutex_lock(&the_mutex);    /* lock th buffer */

    while(buffer[count].num == 0){
      //pthread_cond_signal(&condp);        /* while empty */
      pthread_cond_wait(&condc, &the_mutex);
    }

    //pthread_mutex_lock(&the_mutex);

    sleep(buffer[count].wait_time);
    printf("Consumed %i and slept for %i seconds\n", buffer[count].num, buffer[count].wait_time);

    //pthread_mutex_lock(&the_mutex);
    buffer[count].num = 0;
    buffer[count].wait_time = 0;

    pthread_cond_signal(&condp);    /* signal producer */
    pthread_mutex_unlock(&the_mutex);

    if(count != 31){
      count += 1;
      //printf("Consumer count: %i\n", count);
    }
    else
      count = 0;

    //pthread_cond_signal(&condp);  /* signal producer */
    //pthread_mutex_unlock(&the_mutex); /* unlock */
  }
  pthread_exit(0);
}


int main(int argc, char **argv) {
  pthread_t pro, con;
  srand(time(NULL));

  for (int i = 0; i < 32; i++) {        /* Initialize buffer */
    buffer[i].num = 0;
    buffer[i].wait_time = 0;
  }

  // Initialize the mutex and condition variables
  /* What's the NULL for ??? */
  pthread_mutex_init(&the_mutex, NULL); 
  pthread_cond_init(&condc, NULL);      /* Initialize consumer condition variable */
  pthread_cond_init(&condp, NULL);      /* Initialize producer condition variable */

  // Create the threads
  pthread_create(&con, NULL, consumer, NULL);
  pthread_create(&pro, NULL, producer, NULL);

  // Wait for the threads to finish
  // Otherwise main might run to the end
  // and kill the entire process when it exits.
  pthread_join(con, NULL);
  pthread_join(pro, NULL);
  //pthread_join(&con, NULL);
  //pthread_join(&pro, NULL);

  // Cleanup -- would happen automatically at end of program
  pthread_mutex_destroy(&the_mutex);    /* Free up the_mutex */
  pthread_cond_destroy(&condc);     /* Free up consumer condition variable */
  pthread_cond_destroy(&condp);     /* Free up producer condition variable */

}

输出(程序在1秒后打印第1行,然后在3秒后同时打印第2行和第3行):

Produced 985 and slept for 1 seconds
Consumed 985 and slept for 3 seconds
Produced 540 and slept for 1 seconds

我希望输出看起来像这样:

Produced 985 and slept for 1 seconds
Produced 540 and slept for 1 seconds
Consumed 985 and slept for 3 seconds

1 个答案:

答案 0 :(得分:2)

消费者锁定互斥锁然后睡眠3秒钟。因此,制作人必须等待消费者完成工作/睡眠才能产生其他东西。当锁定到位时,避免睡觉任何一个线程。

编辑: 刚刚编辑了你的代码,这似乎没有信号等工作。试一试:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <pthread.h>
#include <unistd.h>

struct Data {
    int num;
    int wait_time;
}; 

pthread_mutex_t the_mutex;
pthread_cond_t condc, condp;
struct Data buffer[32];

void* producer(void *ptr) {
    int i, w;             /* counter and random wait time */
    struct Data data;
    int count = 0;

    while(1) {
        printf("prod count %d\n",count);
        w = 1;
        sleep(w);
        data.num = rand() % 1000;
        data.wait_time = 3;

        while (buffer[count].num != 0) {
            printf("buffer full, count = %d\n", count);
            sleep(1);
        }

        // Only using the mutex when we want to change the variable.
        pthread_mutex_lock(&the_mutex); 
        buffer[count] = data;
        pthread_mutex_unlock(&the_mutex);

        printf("Produced %i and slept for %i seconds\n", buffer[count].num, w);

        if (count != 31){
            count += 1;
        }
        else
            count = 0;
    }
    pthread_exit(0);
}

void* consumer(void *ptr) {
    int i;
    int count = 0;

    while(1) {       /* lock th buffer */
        printf("cons count %d\n",count);
        while(buffer[count].num == 0){
            printf("buffer empty, count = %d\n", count);
            sleep(1);
        }

        sleep(buffer[count].wait_time);
        printf("Consumed %i and slept for %i seconds\n", buffer[count].num, buffer[count].wait_time);

        pthread_mutex_lock(&the_mutex);
        buffer[count].num = 0;
        buffer[count].wait_time = 0;
        pthread_mutex_unlock(&the_mutex);

        if(count != 31){
            count += 1;
            //printf("Consumer count: %i\n", count);
        }
        else {
            count = 0;
        }
    }
    pthread_exit(0);
}


int main(int argc, char **argv) {
    pthread_t pro, con;
    srand(time(NULL));

    for (int i = 0; i < 32; i++) {        /* Initialize buffer */
        buffer[i].num = 0;
        buffer[i].wait_time = 0;
    }

    // Initialize the mutex and condition variables
    /* What's the NULL for ??? */
    pthread_mutex_init(&the_mutex, NULL); 
    pthread_cond_init(&condc, NULL);      /* Initialize consumer condition variable */
    pthread_cond_init(&condp, NULL);      /* Initialize producer condition variable */

    // Create the threads
    pthread_create(&con, NULL, consumer, NULL);
    pthread_create(&pro, NULL, producer, NULL);

    // Wait for the threads to finish
    // Otherwise main might run to the end
    // and kill the entire process when it exits.
    pthread_join(con, NULL);
    pthread_join(pro, NULL);
    //pthread_join(&con, NULL);
    //pthread_join(&pro, NULL);

    // Cleanup -- would happen automatically at end of program
    pthread_mutex_destroy(&the_mutex);    /* Free up the_mutex */
    pthread_cond_destroy(&condc);     /* Free up consumer condition variable */
    pthread_cond_destroy(&condp);     /* Free up producer condition variable */
}