我想在非線程模式下正常工作的GCC C應用程序中使用線程(第一次!)。當我運行它時,一些線程給出的結果全部爲零而不是所需的答案(我知道用於檢查目的),但是每次運行它時給出零的線程都不相同。給出非零答案的答案是正確的,所以代碼似乎運行正常。我想知道是否有人可以指出哪些地方我可能有不是線程安全的東西。線程能否在不鎖定的情況下寫入相同結構數組的不同元素?
我自己的想法是可能是由於我如何收集結果或可能是內存分配 - 我使用malloc和免費但在StackOverflow其他地方我看到GCC malloc被認爲是線程安全的,如果鏈接-lpthread(我是這樣做)。沒有使用全局/靜態變量 - 一切都作爲函數參數傳遞。
爲了將結果回傳給main,我的線程例程使用了一個結構數組。每個線程寫入此數組的一個獨特元素,因此它們不會嘗試寫入相同的內存。也許我在寫結果時需要使用某種形式的鎖定,即使它們沒有轉到結構數組的相同元素上?
我跟着線程代碼這裏的食譜: 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);
}
對於其他人閱讀此的利益 - 所有的答案是正確的,而問題的答案在標題是YES,線程可以安全地寫入結構的同一陣列的不同元素,我的問題是在調用程序 - 以下是修訂後的代碼片段(現在正常工作):
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在哪裏申報?它是'謎題*'類型嗎?如何計算'ix'?我猜你的問題在你標記爲「工作代碼」的那個塊中。 ;) – 2011-03-15 18:45:25