2015-02-26 2 views
0

Я реализовал проблему синхронизации потоков производителей и потребителей через pthread в соответствии с моим назначением, но мой учитель отклонил, сказав, что использование переменной флага недопустимо, так как это неэффективно. Кто-нибудь может предложить, как это можно реализовать без использования переменной флага.синхронизация потоков без использования переменной флагов

#include <stdio.h> 
#include <stdlib.h> 
#include <pthread.h> 
pthread_mutex_t count_mutex  = PTHREAD_MUTEX_INITIALIZER; 
pthread_cond_t condition_var = PTHREAD_COND_INITIALIZER; 

void *consumer(); 
void *producer(); 
int count = 0; 
#define COUNT_DONE 10 
int flag=0; 
main() 
{ 
    pthread_t thread1, thread2; 
    pthread_create(&thread1, NULL, &producer, NULL); 
    pthread_create(&thread2, NULL, &consumer,NULL); 

    pthread_join(thread1, NULL); 
    pthread_join(thread2, NULL); 

    exit(EXIT_SUCCESS); 
} 

void *consumer() 
{ 
    for(;;) 
    { 
     // Lock mutex and then wait for signal to relase mutex 
     pthread_mutex_lock(&count_mutex); 

     pthread_cond_wait(&condition_var, &count_mutex); 

     while (count!=0) 
     { 
     count--; 
     printf("Counter value consumer: %d\n",count); 
     } 
     pthread_mutex_unlock(&count_mutex); 

     if(count == 0) 
     { 
     return NULL; 

     } 
    } 
} 

void *producer() 
{ 
    for(;;) 
    { 
     pthread_mutex_lock(&count_mutex); 

     if(count==COUNT_DONE ) 
     { 
      flag=1; 
     pthread_cond_signal(&condition_var); 

     } 
     else if(flag==0) 
     { 
      count++; 
      printf("Counter value producer: %d\n",count); 
     } 

     pthread_mutex_unlock(&count_mutex); 
      if(count==0) return (NULL); 

    } 

} 
+0

Обратите внимание, что сигнатуры ваших функций запуска нити неверны. Каждый должен принимать аргумент типа 'void *' (даже если они игнорируют его). –

+0

В графе отображается количество неиспользуемых предметов. Если да, то не может ли он стать 0, как только первый (и пока только) предмет, полученный, будет поглощен, и все закрываются? –

+0

Глобальная переменная 'flag' считывается только функцией' производитель() 'и устанавливается только ее инициализатором и этой функцией. Конечно, он не должен быть глобальным. Я действительно не понимаю, зачем вам это нужно; лучший поток управления в 'manufacturer()' мог бы выполнять ту же работу. –

ответ

0

Учитывая, что потребитель поток блокируется до тех пор, пока сигнал через переменную состояния, что она не рассматривает переменную count, пока после того, как сигнал, что производитель не сигнализировать, пока она не увеличивается count к COUNT_DONE, и что производитель не позже увеличивает count снова, эта версия producer() дает тот же результат более просто:

void *producer() 
{ 
    pthread_mutex_lock(&count_mutex); 

    for(; count < COUNT_DONE; count++) 
    { 
     printf("Counter value producer: %d\n",count); 
    } 

    pthread_cond_signal(&condition_var); 
    pthread_mutex_unlock(&count_mutex); 

    return NULL;  
} 

Хотя эта версия не ждет потребителя закончить, прежде чем он заканчивает сам, он также не идет в ИНЙ конечная петля, если потребитель должен умереть, не потребляя count до нуля.

+0

Обратите внимание, однако, что это не * совершенно * верно, что потребительский поток заблокирован до тех пор, пока не будет сигнализирован. Возможны сильные пробуждения, и если потребитель должен испытать сильное пробуждение до того, как производитель заблокирует мьютекс, тогда он будет работать * до *, производитель производит что-либо. –

0

В классическом потребительском решении производителя будут две условные переменные, которые будут сигнализировать как производить, так и потреблять потоки. Ниже приведена измененная реализация.

#include <stdio.h> 
#include <stdlib.h> 
#include <pthread.h> 
pthread_mutex_t count_mutex  = PTHREAD_MUTEX_INITIALIZER; 
pthread_cond_t condition_var_produce = PTHREAD_COND_INITIALIZER; 
pthread_cond_t condition_var_consume = PTHREAD_COND_INITIALIZER; 

void *consumer(); 
void *producer(); 
int count = 0; 
#define COUNT_DONE 10 
main() 
{ 
    pthread_t thread1, thread2; 
    pthread_create(&thread1, NULL, &producer, NULL); 
    pthread_create(&thread2, NULL, &consumer,NULL); 

    pthread_join(thread1, NULL); 
    pthread_join(thread2, NULL); 

    exit(EXIT_SUCCESS); 
} 

void *consumer() 
{ 
    static int numberOfIterations = 1; 
    while(numberOfIterations--); 
    { 
     pthread_mutex_lock(&count_mutex); 

     while(count!=COUNT_DONE) 
       pthread_cond_wait(&condition_var_consume, &count_mutex); 

     while (count!=0) 
     { 
       printf("Counter value consumer: %d\n",count); 
       count--; 
     } 
     pthread_cond_signal(&condition_var_produce); 
     pthread_mutex_unlock(&count_mutex); 

     if(count == 0) 
     { 
     return NULL; 
     } 
    } 
} 

void *producer() 
{ 
    static int numberOfIterations = 1; 
    while(numberOfIterations--); 
    { 
     pthread_mutex_lock(&count_mutex); 

     while (count!=0) 
       pthread_cond_wait(&condition_var_produce, &count_mutex); 

     while(count!=COUNT_DONE ) 
     { 
      count++; 
      printf("Counter value producer: %d\n",count); 
     } 

     pthread_cond_signal(&condition_var_consume); 
     pthread_mutex_unlock(&count_mutex); 
    } 

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