【发布时间】:2011-03-15 18:37:31
【问题描述】:
我正在尝试在 GCC C 应用程序中使用线程(第一次!),该应用程序在非线程模式下运行良好。当我运行它时,一些线程给出的结果全为零而不是所需的答案(我知道这是为了检查目的),但是每次运行它时给出零的线程都不相同。给出非零答案的答案是正确的,因此代码似乎可以正常运行。我想知道是否有人可以指出我可能有一些不是线程安全的地方。
我自己的想法是这可能是由于我如何收集结果或内存分配 - 我使用 malloc 和 free 但在 StackOverflow 的其他地方我看到如果与 -lpthread 链接 GCC malloc 被认为是线程安全的(我正在做)。没有使用全局/静态变量 - 一切都作为函数参数传递。
为了将结果传回主程序,我的线程例程使用了一个结构数组。每个线程都写入该数组的不同元素,因此它们不会尝试写入相同的内存。也许我在写入结果时需要使用某种形式的锁定,即使它们没有转到结构数组的相同元素?
我在这里遵循了线程代码的配方: https://computing.llnl.gov/tutorials/pthreads/#Abstract
我附上(简化的)代码摘录,以防提供任何线索(我可能错误地省略/修改了某些内容,但我不要求任何人发现错误,只是一般方法)。
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);
}
为了其他阅读本文的人的利益-所有答案都是正确的,并且标题中问题的答案是肯定的,线程可以安全地写入同一结构数组的不同元素,我的问题出在调用例程中- 以下是修改后的代码 sn-p(现在可以正常工作):
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);
}
}
【问题讨论】:
-
嗯。变量 puz 在哪里声明?是
puzzle *类型吗?ix是如何计算的?我猜您的问题出在您标记为“工作代码”的块中。 ;)
标签: c multithreading gcc thread-safety