2017-10-05 7 views
0

Je travaille sur ce problème: prendre une lettre et le nom des mêmes fichiers à partir de la ligne de commande, compter l'occurrence du char dans chaque fichier, en utilisant un thread par fichier, et imprime le nombre total d'occurrences.Compte le char dans le fichier en utilisant thread et mutex

Ceci est mon code:

typedef struct _CharFile{ 

    char c; 
    char *fileName; 

} CharFile; 

pthread_mutex_t count = PTHREAD_MUTEX_INITIALIZER; 
int sum = 0; 

void *CountFile(void *threadarg); 

int main(int argc, const char * argv[]) { 

    pthread_t threads[argc-2]; 
    int chck, t; 
    CharFile cf; 

    for (t=0 ; t<argc-2 ; t++){ 

     cf.c = argv[1][0]; 
     cf.fileName = (char *)argv[t + 2]; 

     chck = pthread_create(&threads[t], NULL, CountFile, (void *) &cf); 
     if (chck){ 
      printf("ERROR; return code from pthread_create() is %d\n", chck); 
      exit(-1); 
     } 

    } 

    printf("%lld occurrences of the letter %c in %lld threads\n", (long long)sum, argv[1][0], (long long)argc-2); 

    return 0; 
} 

void *CountFile(void *threadarg){ 

    FILE *in; 
    CharFile *cf; 
    char c; 
    int counter = 0; 

    cf = (CharFile *) threadarg; 
    in = fopen(cf->fileName, "r"); 

    if (in == NULL){ 

     perror("Error opening the file!\n"); 
     pthread_exit(NULL); 

    } 

    while (fscanf(in, "%c", &c) != EOF){ 

     if(c == cf->c){ 

      counter += 1; 

     } 

    } 

    fclose(in); 

    pthread_mutex_lock(&count); 
    sum += counter; 
    pthread_mutex_unlock(&count); 

    pthread_exit(NULL); 
} 

Je ne reçois pas d'erreur dans l'ouverture de fichier ou dans les créations de fil, mais ma sortie est toujours 0 comme occurrences au total. J'ai également essayé d'imprimer le counter dans les threads et j'ai eu à chaque fois les mêmes nombres dans tous les threads, même si mes fichiers d'entrée sont différents. Est-ce que j'utilise mal le mutex ou y at-il autre chose qui ne va pas?

C'est l'une de mes sorties:

61 occurrences of e in this thread 
0 occurrences of the letter e in 3 threads 
61 occurrences of e in this thread 
61 occurrences of e in this thread 
Program ended with exit code: 9 
+1

Vous n'attendez pas la fin de vos discussions. –

+0

Comment puis-je faire cela? –

+1

Cependant, vous voulez. La façon la plus courante est d'utiliser 'pthread_join'. Mais c'est simple et celui que vous devriez probablement apprendre en premier. –

Répondre

0

Il y a plusieurs problèmes de filetage en jeu ici.

1) Le thread principal continuera de manière asynchrone vers les threads nouvellement engendrés. Étant donné le code, il est très probable que le thread principal se termine et se termine avant la fin des threads CountFile. Sous Linux, lorsque le thread principal revient, l'exécution C exécute un appel système exit_group qui met fin à tous les threads.

Vous devrez ajouter une vérification pour vous assurer que les threads CountFile ont terminé la section de travail appropriée. Dans cet exemple, regardez pthread_join() dans le thread principal.

2) Le stockage 'cf' dans le thread principal est une variable locale de la pile, qui est passée par un pointeur vers chaque thread. Cependant, comme il s'agit du même stockage, plusieurs types d'échecs peuvent se produire. a) l'unité de travail peut être mise à jour par le thread principal pendant qu'un thread de travail y accède. b) le même workunit est envoyé à plusieurs/tous les threads.

Vous pouvez résoudre ceci de plusieurs façons: 'cf' pourrait être un tableau de CharFile pour chaque thread. Ou 'cf' pourrait être alloué dynamiquement pour chaque thread. Le premier est un peu plus de performance et de mémoire efficace, mais le dernier pourrait être mieux structurellement. Particulièrement ce thread principal donne des adresses dans son espace de pile local à un autre thread.

3) Une fois que l'élément # 1 est adressé et que les threads sont terminés avant l'impression du thread principal, l'utilisation du mutex est acceptable. Mais il pourrait être préférable de mettre pthread_mutex_locks autour de l'accès au thread principal de 'sum' de toute façon. Il n'est peut-être pas nécessaire d'utiliser ce code, mais les futurs refacteurs du code pourraient changer cela.