2010-09-21 24 views
0

Voici donc mon scénario. Tout d'abord, j'ai une structure -pthreads - le thread créé précédemment utilise une nouvelle valeur (mise à jour après la création du thread)

struct interval 
{ 
    double lower; 
    double higher; 
} 

Maintenant, ma fonction de fil -

void* thread_function(void* i) 
{ 
    interval* in = (interval*)i; 
    double a = in->lower; 
    cout << a; 
    pthread_exit(NULL) 
} 

En principal, disons que je crée ces 2 fils -

pthread_t one,two; 
interval i; 

i.lower = 0; i.higher = 5; 
pthread_create(&one,NULL,thread_function,&i); 

i.lower=10; i.higher = 20; 
pthread_create(&two,NULL,thread_function, &i); 

pthread_join(one,NULL); 
pthread_join(two,NULL); 

Voilà le problème. Idéalement, le fil "un" devrait imprimer 0 et le fil "deux" devrait imprimer 10. Cependant, cela n'arrive pas. De temps en temps, je finis par avoir deux 10.

Est-ce intentionnel? En d'autres termes, au moment où le thread est créé, la valeur dans i.lower a déjà été modifiée dans main, donc les deux threads finissent par utiliser la même valeur?

Répondre

3

Est-ce intentionnel?

Oui. Il n'est pas spécifié quand exactement les threads commencent et quand ils accèderont à cette valeur. Vous devez donner à chacun d'entre eux sa propre copie des données.

3

Votre application est non-déterministe.
Il est impossible de savoir quand un thread sera programmé pour s'exécuter.

Remarque: La création d'un thread ne signifie pas qu'il commencera à s'exécuter immédiatement (ou même d'abord). Le deuxième thread créé peut commencer à s'exécuter avant le premier (tout dépend du système d'exploitation et du matériel).

Pour obtenir un comportement déterministe, chaque thread doit recevoir ses propres données (qui ne sont pas modifiées par le thread principal).

pthread_t one,two; 
interval oneData,twoData 

oneData.lower = 0; oneData.higher = 5; 
pthread_create(&one,NULL,thread_function,&oneData); 

twoData.lower=10; twoData.higher = 20; 
pthread_create(&two,NULL,thread_function, &twoData); 

pthread_join(one,NULL); 
pthread_join(two,NULL); 

Je ne l'appellerais pas par conception.
Je préférerais me référer à cela comme un effet secondaire de la politique d'ordonnancement. Mais le comportement observé est ce que je m'attendrais.

1

Ceci est la «condition de course» classique; où les résultats varient en fonction du thread qui gagne la «course». Vous n'avez aucun moyen de savoir quel fil va «gagner» chaque fois.

1

Votre analyse du problème est correcte; vous n'avez simplement aucune garantie que le premier thread créé sera capable de lire i.lower avant que les données ne soient modifiées sur la ligne suivante de votre fonction principale. C'est en quelque sorte le cœur de la raison pour laquelle il peut être difficile de penser à la programmation multithread au début.

La solution avant directement à votre problème immédiat est de garder différents intervalles avec des données différentes, et passer un contrat distinct à chaque fil, à savoir

interval i, j; 
i.lower = 0; j.lower = 10; 
pthread_create(&one,NULL,thread_function,&i); 
pthread_create(&two,NULL,thread_function,&j); 

Ce sera bien sûr résoudre votre problème immédiat. Mais bientôt, vous vous demanderez probablement quoi faire si vous voulez que plusieurs threads utilisent réellement les mêmes données. Que faire si le thread 1 veut apporter des modifications à i et que le thread 2 veut en tenir compte? Il ne serait guère utile de faire de la programmation multithread si chaque thread devait garder sa mémoire séparée des autres (bien, laissant le message sortir de l'image pour l'instant). Entrez les verrous de mutex!Je pensais que je vous donnerais un coup de tête que vous aurez envie d'examiner ce sujet plus tôt que plus tard, car il vous aidera également à comprendre les bases de discussions en général et le changement de mentalité qui va de pair avec multithread la programmation.

me semble me rappeler que this est une bonne courte introduction à pthreads, y compris la mise en route avec verrouillage compréhension etc.