2017-08-24 2 views
0

gars bien, nous avons défini 2 mutex: bar_mutex (utilisé entre N fils de la barre) et writer_mutex (utilisé dans la barre enfile un fil de observateur). L'auteur mutex est utilisé pour éviter les valeurs étranges de la variable k_total, là je modifie une variable globale mais à certains moments particuliers cette variable devient 0.0 et l'autre thread l'utilise avec cette valeur. Afin d'éviter cela, j'ai ajouté le writer_mutex mais le problème persiste. Qu'est-ce que je fais mal? Je vais coller les parties importantes du code.comportement inattendu dans pthread mutex

if (k_total < 1 && b->cm <=20) { 
    b->cm = b->cm + 10; //Usando este valor calculamos el deltak 
    /* printf("\nThread yendo hacia abajo\n"); */ 
    if (b->direction == UP) { 
     b->direction = DOWN; 
     changed_direction = true; 
    } else { 
     changed_direction = false; 
    } 
} else if(k_total > 1 && b->cm >=-20) { 
    b->cm = b->cm - 10; //Usando este valor calculamos el deltak 
    /* printf("\nThread yendo hacia arriba\n"); */ 
    if (b->direction == DOWN) { 
     b->direction = UP; 
     changed_direction = true; 
    } else { 
     changed_direction = false; 
    } 
} 

Dans cette partie de la fonction move_bar k_total est prise comme 0 au lieu de la valeur correcte ... Pour éviter ce j'ai ajouté le writer_mutex mais il ne fonctionne toujours pas

enter image description here

ici vous pouvez voir la KTOTAL variable globale est envoyé comme 0 dans certains point ... J'essaie d'éviter cela.

Je vais ajouter les parties principales du code.

void 
start_threads(struct bar* bars) { 
    int i; 
    pthread_t threads[NUM_THREADS + 1]; 
    bars = (struct bar*)malloc(sizeof(struct bar) * NUM_THREADS); 
    init_variables(); 
    pthread_mutex_init(&bar_mutex, NULL); 
    pthread_mutex_init(&write_mutex, NULL); 
    pthread_cond_init(&unstable_state, NULL); 

    for (i = 1; i < NUM_THREADS + 1; i++) { 
     fill_bar(&bars[i - 1], i); 
    } 

    pthread_attr_init(&attr); 
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 
    // creating the 4 threads that handle each bar 
    for (i = 0; i < NUM_THREADS; i++) { 
     pthread_create(&threads[i], &attr, move_bar, (void *)&bars[i]); 
    } 
    //thread used to check if system is stable and change its k_total 
    pthread_create(&threads[NUM_THREADS], &attr, check_stable, (void*)bars); 

    /* Wait for all threads to complete */ 
    for (i=0; i<NUM_THREADS + 1; i++) { 
     pthread_join(threads[i], NULL); 
    } 
} 

void* 
check_stable(void* bars) { 
    struct bar* wires = (struct bar*) bars ; 
    while (true) { 
     pthread_mutex_lock(&write_mutex); 
     k_total = 0.0; 
     for (int i = 0; i < NUM_THREADS; ++i) { 
      k_total += getDeltaKValue(wires[i].cm); 
     } 

     char str[25]; 
     sprintf(str,"deltak=%lf", k_total); 
     doPost("deltak",str); 

     k_total = k_value + k_total; 

     sprintf(str,"kparcial=%lf",k_value); 
     doPost("kparcial",str); 
     sprintf(str,"ktotal=%lf", k_total); 
     doPost("ktotal",str); 
     if ((double)k_total != (double)1.0) { 
      unbalanced = true; 
      pthread_cond_signal(&unstable_state); 
     } else { 
      unbalanced = false; 
     } 
     pthread_mutex_unlock(&write_mutex); 
     sleep(1); 
    } 
} 

void* 
move_bar(void *bar) { 
    struct bar* b = (struct bar*) bar; 
    clock_t start = clock(); 
    bool changed_direction = false; 
    while (true) { 
     pthread_mutex_lock(&bar_mutex); 
     while (unbalanced == false) 
      pthread_cond_wait(&unstable_state, &bar_mutex); 
     pthread_mutex_lock(&write_mutex); 
     if (k_total < 1 && b->cm <=20) { 
      b->cm = b->cm + 10; //Usando este valor calculamos el deltak 
      /* printf("\nThread yendo hacia abajo\n"); */ 
      if(b->direction == UP) { 
       b->direction = DOWN; 
       changed_direction = true; 
      } else { 
       changed_direction = false; 
      } 
     } else if (k_total > 1 && b->cm >=-20) { 
      b->cm = b->cm - 10; //Usando este valor calculamos el deltak 
      /* printf("\nThread yendo hacia arriba\n"); */ 
      if(b->direction == DOWN) { 
       b->direction = UP; 
       changed_direction = true; 
      } else { 
       changed_direction = false; 
      } 
     } 

     k_total = 0.0; 
     for (int i = 0; i < NUM_THREADS; ++i) { 
      k_total += getDeltaKValue(bars[i].cm); 
     } 
     char str[25]; 
     if ((double)k_total != (double)1.0) { 
      unbalanced = true; 
     } else { 
      printf("\nBALANCED"); 
      unbalanced = false; 
     } 

     pthread_mutex_unlock(&write_mutex); 

     if (changed_direction) { 
      sleep(CHANGE_DIRECTION); 
     } 
     sleep(MOVEMENT_TIME); 

     sprintf(str,"id=%ld&cm=%d",b->id, b->cm); 
     doPost("barValue",str); 

     /* printf("\nEnding thread %ld", b->id); */ 
     changed_direction = false; 
     pthread_mutex_unlock(&bar_mutex); 
     sleep(1); 
    } 
    pthread_exit(NULL); 
} 
+1

Pour efficacement debug, la 1ère chose à faire est d'ajouter la vérification des erreurs et l'enregistrement de tous les appels *** de fonctions pertinentes * ** (le 'pthread _ *()' appelle ici, au moins). – alk

+0

Peut-être mieux déplacer ce 'sprintf (str," id =% ld & cm =% d ", b-> id, b-> cm);' dans la section critique protégée par 'write_mutex'? – alk

Répondre

0

Ok les gars, le problème n'était pas là. Ce code fonctionne vraiment. En utilisant gdb j'ai vu qu'il y avait 2 variables globales barres avec le même nom mais avec des références différentes, parce que je faisais 2 mallocs pour la même variable et j'avais utilisé cette variable dans 2 différentes fonctions de mise à jour des structures de bot au lieu de seulement 1 ... Je viens de retirer le malloc inattendu et tout a bien fonctionné.