2017-10-06 20 views
0

Je suis novice en C et je connais les sémaphores. J'essaie de mettre en place une sorte de situation complexe des philosophes de la restauration en utilisant des pthreads, des mutex et des sémaphores.Sortie de la fonction pthread inattendue

L'idée est qu'un sémaphore, représentant un serveur, place des personnes à deux tables (4 places chacune, 8 au total). Chaque table est également contrôlée par un sémaphore de comptage. Chaque plaque est contrôlée par un mutex pour éviter les conditions de course. Chaque personne est représentée par un fil.

Je ne vois pas pourquoi dans mon code le même client continue de manger, et ne semble pas s'incrémenter.

code:

#include <stdio.h> 
#include <stdlib.h> 
#include <pthread.h> 
#include <semaphore.h> 


sem_t server_sem; 
int server_pshared; 
int server_ret; 
int server_count = 10; 

sem_t tablea_sem; 
int tablea_pshared; 
int tablea_ret; 
int tablea_count = 4; 

sem_t tableb_sem; 
int tableb_pshared; 
int tableb_ret; 
int tableb_count = 4; 



//server_ret = serm_open("serverSem", O_CREAT | O_EXCL, 0644, server_count); 

int customer_count = 10; 
pthread_t customer[10]; 
//pthread_t plates[8] 

int plate_count = 8; 
pthread_mutex_t plates[8]; 


void *eat(void *i) { 

    int n = *((int *) i); 

    pthread_mutex_lock(&plates[n]); 
    printf("Customer %d is eating\n", n); 
    sleep(5); 
    pthread_mutex_unlock(&plates[n]); 
    printf("Customer %d is finished eating\n", n); 

    return (NULL); 
} 

int main() { 


    server_ret = sem_init(&server_sem, 1, server_count); 
    tablea_ret = sem_init(&tablea_sem, 1, tablea_count); 
    tableb_ret = sem_init(&tableb_sem, 1, tableb_count); 

    //customer = (pthread_t[10] *)malloc(sizeof(customer)); 

    printf ("starting thread, semaphore is unlocked.\n"); 

    int i; 
    int j; 
    int k; 




    for(i=0;i<plate_count;i++) { 
     pthread_mutex_init(&plates[i],NULL); 
     printf("Creating mutex for plate %d\n", i); 
    } 

    sem_wait(&server_sem); 

    for (j=0;j<customer_count;j++) { 
     //pthread_create(&customer[j],NULL,(void *)eat,&j); 
     if (j<4) { 
     sem_wait(&tablea_sem); 
     sem_post(&tableb_sem); 
     pthread_create(&customer[j],NULL,(void *)eat,&j); 

     printf("Creating thread for customer %d\n", j); 
     } 
     else { 
     sem_post(&tablea_sem); 
     sem_wait(&tableb_sem); 
     pthread_create(&customer[j],NULL,(void *)eat,&j); 

     printf("Creating thread for customer %d\n", j); 
     } 

    } 

    for(k=0;k<customer_count;k++) { 
     pthread_join(customer[k],NULL); 
     printf("Joining thread %d\n", k); 
    } 

    for(i=0;i<plate_count;i++) { 
     pthread_mutex_destroy(&plates[i]); 
    } 

    return 0; 
    } 

Sortie de la console:

starting thread, semaphore is unlocked. 
Creating mutex for plate 0 
Creating mutex for plate 1 
Creating mutex for plate 2 
Creating mutex for plate 3 
Creating mutex for plate 4 
Creating mutex for plate 5 
Creating mutex for plate 6 
Creating mutex for plate 7 
Creating thread for customer 0 
Creating thread for customer 1 
Creating thread for customer 2 
Creating thread for customer 3 
Creating thread for customer 4 
Creating thread for customer 5 
Creating thread for customer 6 
Creating thread for customer 7 
Creating thread for customer 8 
Creating thread for customer 9 
Customer 10 is eating 
Customer 10 is eating 
Customer 10 is eating 
Customer 10 is eating 
Customer 10 is eating 
Customer 10 is eating 
Customer 10 is eating 
Customer 10 is eating 
Customer 10 is eating 
Customer 10 is eating 
Customer 10 is finished eating 
Customer 10 is finished eating 
Customer 10 is finished eating 
Customer 10 is finished eating 
Customer 10 is finished eating 
Customer 10 is finished eating 
Customer 10 is finished eating 
Customer 10 is finished eating 
Customer 10 is finished eating 
Customer 10 is finished eating 
Joining thread 0 
Joining thread 1 
Joining thread 2 
Joining thread 3 
Joining thread 4 
Joining thread 5 
Joining thread 6 
Joining thread 7 
Joining thread 8 
Joining thread 9 

EDIT:

Mise à jour le dernier paramètre de pthread_create résout le problème des clients incrémenter:

pthread_create(&customer[j],NULL,(void *)eat,(void *) (intptr_t) j); 

Cependant, il commence à 6, puis il y a le type de problème de l'index hors limites.

Sortie de la console maintenant:

starting thread, semaphore is unlocked. 
Creating mutex for plate 0 
Creating mutex for plate 1 
Creating mutex for plate 2 
Creating mutex for plate 3 
Creating mutex for plate 4 
Creating mutex for plate 5 
Creating mutex for plate 6 
Creating mutex for plate 7 
Creating thread for customer 0 
Creating thread for customer 1 
Creating thread for customer 2 
Creating thread for customer 3 
Creating thread for customer 4 
Creating thread for customer 5 
Creating thread for customer 6 
Creating thread for customer 7 
Creating thread for customer 8 
Creating thread for customer 9 
Customer 6 is eating 
Customer 7 is eating 
Illegal instruction (core dumped) 

Répondre

3

Avec la ligne

pthread_create(&customer[j],NULL,(void *)eat,&j); 

vous passez l'adresse du j variable au fil comme argument. Et vous passez la même adresse à la même variable à tous les threads.

Lorsque la boucle est terminée, la valeur de j sera égale à customer_count et c'est ce que les threads peuvent utiliser comme index dans le tableau. Et c'est de de la malédiction hors limites menant à comportement indéfini. En ce qui concerne une solution possible, il s'agit en fait d'un endroit où il est accepté de convertir une valeur entière en un pointeur, puis de le renvoyer dans le thread. Cela doit être fait en quelques étapes cependant. Tout d'abord lors de la création du fil:

pthread_create(&customer[j],NULL,(void *)eat, (void *) (intptr_t) j); 

Ensuite, dans le fil lui-même:

int n = (int) (intptr_t) i; 
+0

qui fait l'affaire - mais il commence à 6. Sous la direction un peu ma question si vous avez un aperçu sur ce point. – user25976

+1

@ user25976 L'ordre dans lequel les threads s'exécutent est indéterminé. L'OS pourrait les exécuter dans l'ordre qu'il juge approprié. –

+1

@ user25976 Comme pour le crash, vous devez utiliser un débogueur pour le localiser. Et posez probablement une nouvelle question à ce sujet si vous ne pouvez pas le comprendre avec l'aide d'un débogueur. –