2017-10-13 2 views
0

Ich schrieb mein erstes Multithread-Programm und zum größten Teil funktioniert es. Das Shared-Buffer-Array wird anfänglich mit -1 gefüllt, was dem Hersteller anzeigt, dass es leer ist und gefüllt werden muss. Der Produzent füllt dann den geteilten Puffer mit zufälligen Werten von 1 bis 10, und die Erzeuger nehmen abwechselnd den Puffer auf. Der Produzent signalisiert dann dem Verbraucher, dass er ein Element des Puffers gefüllt hat und es konsumiert. Es gibt 120 Elemente, die der Produzent füllen muss und der Verbraucher sollte jeden Eintrag. Das Programm funktioniert einwandfrei, bis es zu Element 110 kommt. Es friert dann ein und ich kann nicht herausfinden warum. Wie behebe ich das?Multithread-Programm friert kurz vor der Fertigstellung ein

Hier ist ein Ausschnitt des Ausgangs.

Item: 85, Consuming value 8, my thread id is: 1216 
Item: 86, Consuming value 7, my thread id is: 298320 
Signal 
Producer thread 231296 and value: 0 
Producer thread 297552 and value: 2 
Producer thread 298576 and value: 0 
Item: 87, Consuming value 9, my thread id is: 297808 
Signal 
Producer thread 960 and value: 3 
Producer thread 298064 and value: 2 
Item: 88, Consuming value 3, my thread id is: 231744 
Item: 89, Consuming value 7, my thread id is: 298320 
Item: 90, Consuming value 3, my thread id is: 1216 
Item: 91, Consuming value 7, my thread id is: 298832 
Signal 
Producer thread 231296 and value: 3 
Producer thread 297552 and value: 8 
Producer thread 298576 and value: 6 
Item: 92, Consuming value 2, my thread id is: 297808 
Signal 
Producer thread 960 and value: 9 
Producer thread 298064 and value: 7 
Item: 93, Consuming value 5, my thread id is: 298320 
Item: 94, Consuming value 2, my thread id is: 298832 
Item: 95, Consuming value 0, my thread id is: 1216 
Item: 96, Consuming value 2, my thread id is: 231744 

Dies ist mein Code

#include <stdio.h> 
#include <string.h> 
#include <unistd.h> 
#include <stdlib.h> 
#include <pthread.h> 
#include <stdint.h> 


#define THREADS 5 
#define ELEMENTS 120 


pthread_t tid_producer[THREADS], tid_consumer[THREADS]; 
int value = 0; 
int saveValue = 0; 
void *produce(void *arg); 
void *consume(void *arg); 
int producerCount =0; 
int consumerCount = ELEMENTS; 

struct { 
    pthread_mutex_t mutex; 
    int index; 
    int value; 
    int MyShBuff[ELEMENTS]; 
} add = {PTHREAD_MUTEX_INITIALIZER, 0, 0}; 


    struct{ 
    pthread_mutex_t mutex; 
    pthread_cond_t  cond; 
    int nready; 
    int value; 
    int empty; 
    int counter; 

    /* number ready for consumer */ 
} nready = {PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER,0, -2, ELEMENTS}; 

int main() 
{ 

    int i, j, k; 

    //Ready buffer for producers 
    for (i =0; i < ELEMENTS; i++) 
    { 
     add.MyShBuff[i]=-1; 
    } 



    for(j = 0; j < THREADS; j++) { 

    pthread_create(&tid_producer[j], NULL, &produce, NULL); 
    pthread_create(&tid_consumer[j], NULL, &consume, NULL); 
} 



/* wait for all producers and the consumer*/ 

    for(k = 0; k < THREADS; k++) { 
     pthread_join(tid_producer[k], NULL); 
     pthread_join(tid_consumer[k], NULL);  
    } 

    /* Clean up and exit */ 

    pthread_mutex_destroy(&nready.mutex); 
    pthread_mutex_destroy(&add.mutex); 
    pthread_cond_destroy(&nready.cond); 
    pthread_exit(NULL); 

    exit(0);  
    return 0; 
} 

void *produce(void *arg) 
    { 
    int i = 0; 


    for (; ;) 
    { 
     pthread_mutex_lock(&add.mutex); 
     if(add.index >= ELEMENTS) 
     { 

      pthread_mutex_unlock(&add.mutex); 
      return NULL; 
     } 
     if(add.MyShBuff[add.index] == -1) 
     { 
     add.value = rand() % 10 + 0; 
     add.MyShBuff[add.index] = add.value; 
     printf("Producer thread %d and value: %d\n" ,pthread_self(), add.MyShBuff[add.index]); 
     add.index++; 
     } 
     pthread_mutex_unlock(&add.mutex); 
     pthread_mutex_lock(&nready.mutex); 

     if(nready.nready == 0) 
     { 
     pthread_cond_broadcast(&nready.cond); 
     printf("Signal\n"); 
     } 

     nready.nready++; 
     pthread_mutex_unlock(&nready.mutex); 

     } 


    } 


void *consume(void *arg) 
{ 

pthread_mutex_lock(&nready.mutex); 

    while(nready.empty != 0) 
    { 

    while (nready.nready == 0) 
    { 


     pthread_cond_wait(&nready.cond,&nready.mutex); 


     pthread_mutex_lock(&add.mutex); 
     printf(" Item: %d, Consuming value %d, my thread id is: %d\n", nready.counter, add.MyShBuff[nready.counter], pthread_self()); 
     add.MyShBuff[nready.counter] = -2; 
     pthread_mutex_unlock(&add.mutex); 

     nready.counter++; 
     nready.empty--; 


    } 

    nready.nready--; 
    pthread_mutex_unlock(&nready.mutex); 
    } 


    return NULL; 


} 
+1

Versuch zu debuggen, indem Diskussionsthemen zu 1. Zur Zeit reduziert, wenn verbrauchen tritt nach Produkten Mutex warten hat ausgestrahlt getan, Ihr Programm friert ein. – miradham

+1

Zusätzlich zu dem, was Miradham sagte, sperrst du 'nready.mutex' einmal in' consume' ein, entsperrst es aber bei jeder Iteration der äußeren Schleife, was unmöglich sein kann. –

Antwort

1

Wie in Kommentaren darauf, Sie von Mutex verwenden falsch ist in verbrauchen (man stelle sich die während conditon falsch ist, wird der Faden verlassen, ohne die Mutex Freigabe) Außerdem Ich würde vorschlagen, die Anzahl der Variablen zu begrenzen, die dieselbe Information enthalten (leer, Zähler), wodurch der Fluss schwer zu folgen ist. Schließlich haben Sie auch einen Fehler in Ihrem pthread_wait_cond: sieht Does pthread_cond_wait(&cond_t, &mutex); unlock and then lock the mutex? oder irgendeine andere Frage, die die Verwendung von pthread_wait_cond erklären: sie betonen, dass das Prädikat MAY nach der Rückkehr, wahr sein, was bedeuten Sie es erneut testen müssen vor dem Start mehr Berechnung, die erfordert, dass das Prädikat wahr ist.

Ich habe ein bisschen Ihren Code umgeschrieben, damit es funktioniert; Ich hoffe, dass ich nicht noch etwas übersehen haben, aber das kann Ihnen helfen, weiter zu gehen:

#include <stdio.h> 
#include <string.h> 
#include <unistd.h> 
#include <stdlib.h> 
#include <pthread.h> 
#include <stdint.h> 


#define THREADS 5 
#define ELEMENTS 120 


pthread_t tid_producer[THREADS], tid_consumer[THREADS]; 
int value = 0; 
int saveValue = 0; 
void *produce (void *arg); 
void *consume (void *arg); 
int producerCount = 0; 
int consumerCount = ELEMENTS; 

struct 
{ 
    pthread_mutex_t mutex; 
    int index; 
    int value; 
    int MyShBuff[ELEMENTS]; 
} add = { PTHREAD_MUTEX_INITIALIZER, 0, 0 }; 


struct 
{ 
    pthread_mutex_t mutex; 
    pthread_cond_t cond; 
    int nready; 
    int value; 
    int empty; 
    int counter; 

    /* number ready for consumer */ 
} nready = { PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, 0, -2, ELEMENTS, 0 }; 

int main(int argc, char **argv) 
{ 
    //Ready buffer for producers 
    for (int i = 0; i < ELEMENTS; i++) { 
     add.MyShBuff[i] = -1; 
    } 


    for (int j = 0; j < THREADS; j++) { 
     pthread_create (&tid_producer[j], NULL, &produce, NULL); 
     pthread_create (&tid_consumer[j], NULL, &consume, NULL); 
    } 

    /* wait for all producers and the consumer */ 
    for (int k = 0; k < THREADS; k++) { 
     pthread_join (tid_producer[k], NULL); 
     pthread_join (tid_consumer[k], NULL); 
    } 

    /* Clean up and exit */ 
    pthread_mutex_destroy (&nready.mutex); 
    pthread_mutex_destroy (&add.mutex); 
    pthread_cond_destroy (&nready.cond); 

    return 0; 
} 

void *produce(void *dummy) 
{ 
    pthread_mutex_lock (&add.mutex); 

    while (add.index < ELEMENTS) { 
     if (add.MyShBuff[add.index] == -1) 
     { 
      add.value = rand() % 10 + 0; 
      add.MyShBuff[add.index] = add.value; 
      printf("Producer thread %ld and value: %d\n" ,pthread_self(), add.MyShBuff[add.index]); 
      add.index++; 
     } 
     pthread_mutex_unlock (&add.mutex); 

     pthread_mutex_lock (&nready.mutex); 
     { 
      if (nready.nready == 0) 
      { 
       pthread_cond_broadcast (&nready.cond); 
       printf ("Signal\n"); 
      } 
      nready.nready++; 
     } 
     pthread_mutex_unlock (&nready.mutex); 

     pthread_mutex_lock (&add.mutex); 
    } 

    pthread_mutex_unlock (&add.mutex); 

    return NULL; 
} 


void *consume(void *dummy) 
{ 
    pthread_mutex_lock (&nready.mutex); 

    while (nready.empty != 0) 
    { 
     // you also need to check it is not time to leave... 
     while (nready.nready == 0 && nready.empty != 0) { 
      pthread_cond_wait (&nready.cond, &nready.mutex); 
     } 

     if (nready.empty == 0) { 
      break; 
     } 

     pthread_mutex_lock (&add.mutex); 
     printf(" Item: %d, Consuming value %d, my thread id is: %ld\n", nready.counter, add.MyShBuff[nready.counter], pthread_self()); 
     add.MyShBuff[nready.counter] = -2; 

     pthread_mutex_unlock (&add.mutex); 

     nready.counter++; 
     nready.empty--; 

     nready.nready--; 
    } 

    pthread_mutex_unlock (&nready.mutex); 

    return NULL; 
} 
Verwandte Themen