J'essaie d'utiliser des threads (pour la première fois!) Dans une application GCC C qui fonctionne bien en mode non-threaded. Quand je l'exécute, certains threads donnent des résultats qui sont tous à zéro au lieu des réponses requises (que je connais à des fins de vérification), mais les threads donnant des zéros ne sont pas les mêmes chaque fois que je l'exécute. Ceux qui donnent des réponses non nulles sont corrects, donc le code semble fonctionner correctement. Je me demande si quelqu'un peut signaler des domaines où je pourrais avoir quelque chose qui n'est pas sûr pour les threads. Mes propres pensées sont peut-être en raison de la façon dont je collectionne les résultats ou l'allocation de mémoire - j'utilise malloc et libre mais ailleurs dans StackOverflow je vois que GCC malloc est considéré comme thread-safe si -lpthread (que je suis Faire). Rien n'utilise les variables globales/statiques - tout est passé comme arguments de fonction.Les threads peuvent-ils écrire sur différents éléments du même réseau de structures sans verrouillage?
Afin de renvoyer les résultats à main, ma routine threadée utilise un tableau de structures. Chaque thread écrit dans un élément distinct de ce tableau, ainsi ils n'essaient pas d'écrire dans la même mémoire. Peut-être que je dois utiliser une certaine forme de verrouillage lors de l'écriture des résultats, même si elles ne vont pas au même élément du tableau de la structure?
J'ai suivi la recette pour le code threadé ici: https://computing.llnl.gov/tutorials/pthreads/#Abstract
Je joindre des extraits de code (simplifié) en cas cela donne des indices (je l'ai omis/quelque chose modifié de manière incorrecte, mais je ne demande pas à quiconque de repérer bugs, juste la méthodologie générale).
typedef struct p_struct { /* used for communicating results back to main */
int given[CELLS];
int type;
int status;
/*... etc */
} puzstru;
typedef struct params_struct { /* used for calling generate function using threads */
long seed;
char *text;
puzzle *puzzp;
bool unique;
int required;
} paramstru;
/* ========================================================================================== */
void *myfunc(void *spv) /* calling routine for use by threads */
{
paramstru *sp=(paramstru *)spv;
generate(sp->seed, sp->text, sp->puzzp, sp->unique, sp->required);
pthread_exit((void*) spv);
}
/* ========================================================================================== */
int generate(long seed, char *text, puzstru *puzzp, bool unique, int required)
{
/* working code , also uses malloc and free,
puts results in the element of a structure array pointed to by "puzzp",
which is different for each thread
(see calling routine below : params->puzzp=puz+thr;)
extract as follows: */
puzzp->given[ix]=calcgiven[ix];
puzzp->type=1;
puzzp->status=1;
/* ... etc */
}
/* ========================================================================================== */
int main(int argc, char* argv[])
{
pthread_t thread[NUM_THREADS];
pthread_attr_t threadattr;
int thr,threadretcode;
void *threadstatus;
paramstru params[1];
/* ....... ETC */
/* set up params structure for function calling parameters */
params->text=mytext;
params->unique=TRUE;
params->required=1;
/* Initialize and set thread detached attribute */
pthread_attr_init(&threadattr);
pthread_attr_setdetachstate(&threadattr, PTHREAD_CREATE_JOINABLE);
for(thr=0; thr<NUM_THREADS; thr++)
{
printf("Main: creating thread %d\n", thr);
params->seed=ran_arr_next(startingseeds);
params->puzzp=puz+thr;
threadretcode = pthread_create(&thread[thr], &threadattr, myfunc, (void *)params);
if (threadretcode)
{
printf("ERROR; return code from pthread_create() is %d\n", threadretcode);
exit(-1);
}
}
/* Free thread attribute and wait for the other threads */
pthread_attr_destroy(&threadattr);
for(thr=0; thr<NUM_THREADS; thr++)
{
threadretcode = pthread_join(thread[thr], &threadstatus);
if (threadretcode)
{
printf("ERROR; return code from pthread_join() is %d\n", threadretcode);
exit(-1);
}
printf("Main: completed join with thread %d having a status of %ld\n",thr,(long)threadstatus);
}
/* non-threaded code, print results etc ............. */
free(startingseeds);
free(puz);
printf("Main: program completed. Exiting.\n");
pthread_exit(NULL);
}
Pour le bénéfice des autres la lecture de ce - toutes les réponses sont correctes, et la réponse à la question dans le titre est OUI, les fils peuvent écrire en toute sécurité à différents éléments du même tableau de structures, mon problème était dans la routine d'appel - ce qui suit est l'extrait de code modifié (fonctionne maintenant très bien):
paramstru params[NUM_THREADS];
for(thr=0; thr<NUM_THREADS; thr++)
{
printf("Main: creating thread %d\n", thr);
/* set up params structure for function calling parameters */
params[thr].text=mytext;
params[thr].unique=TRUE;
params[thr].required=1;
params[thr].seed=ran_arr_next(startingseeds);
params[thr].puzzp=puz+thr;
threadretcode = pthread_create(&thread[thr], &threadattr, myfunc, (void *)¶ms[thr]);
if (threadretcode)
{
printf("ERROR; return code from pthread_create() is %d\n", threadretcode);
exit(-1);
}
}
Hmm. Où est la variable puz déclarée? Est-ce de type 'puzzle *'? Comment 'ix' est-il calculé? Je suppose que votre problème est dans le bloc que vous avez marqué comme "code de travail". ;) –