2016-04-03 2 views
3

Я пытаюсь создать программу-потребитель-продюсер, где номера производителей потребительских потоков заполняют массив, а потребительский поток печатает числа, которые заполняют массив. В настоящее время я могу заполнить массив и передавать данные взад и вперед между потоками потребителей/производителей, но я хочу, чтобы производитель создавал числа быстрее, чем потребитель обрабатывает их.Блоки потоков, когда он не предполагается

В настоящий момент количество произведено каждые 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 */ 

} 

Output (программа печатает на 1-й линии через 1 секунд, затем печатает как 2-й и 3-й, в то же время, после 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 
+0

'while (buffer [count] .num! = 0)' Это условие, используемое 'производителем', чтобы определить, следует ли блокировать условное. Он блокирует блок производителя, как только в буфере есть что-либо. Если вам нужно другое поведение, вы должны изменить условие. Например, если вы хотите, чтобы он блокировал, если есть уже 3 элемента, то измените на: 'while (buffer [count] .num == 3)' – kaylum

ответ

2

потребитель блокировки мьютекса затем спит в течение 3 секунд. Таким образом, продюсер должен ждать, пока потребитель закончит работу/сон, прежде чем он сможет произвести что-то еще. Избегайте спать нить при блокировке.

EDIT: Редактировал ваш код немного, и это, похоже, работает без сигналов и т. Д. Здесь. Дайте ему обход:

#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 */ 
} 
+0

Как я могу избежать использования сна? Производитель должен занять 1 секунду, чтобы произвести число, и потребитель должен занять 3 секунды. –

+0

Использование сна в порядке, но просто заблокируйте мьютекс у потребителя после сна, а не перед ним. Блокировка вызова перед установкой num в 0 – Pedro

+0

В случае производителя, поскольку внутренний цикл while (который спящий, если 'num! = 0') делает _not_ использование блокировки [не _need_ to], это может потребовать, чтобы' buffer' был объявленный 'volatile', в зависимости от того, какой код генерирует компилятор –

Смежные вопросы