[英]C - How to terminate all threads after one of them signals the main thread with a condition variable?
[英]Condition variable blocks on main thread
我想使用條件變量最多啟動N個線程來處理一個巨大目錄(1M個文件)中的所有文件。
該代碼似乎可以正常工作,但一段時間后,它將在主線程中阻塞。 在令人沮喪的代碼下面:
void* run(void* ctx)
{
clientCtx* client = (clientCtx*)ctx;
printf("New file from thread %d: %s\n", client->num, client->filename);
free(client->filename);
pthread_mutex_lock(&clientFreeMutex);
client->state = IDLE_STATE;
pthread_cond_signal(&clientFreeCond);
printf("Thread %d is free\n", client->num);
pthread_mutex_unlock(&clientFreeMutex);
return NULL;
}
int main(int argc, char** argv)
{
pthread_t client[MAX_CLIENT] = {0};
clientCtx ctx[MAX_CLIENT] = {0};
DIR* directory = NULL;
struct dirent* element = NULL;
/* Initialize condition variable for max clients */
pthread_mutex_init(&clientFreeMutex, NULL);
pthread_cond_init(&clientFreeCond, NULL);
/* Initialize contexts for clients */
for (int cnt = 0; cnt < MAX_CLIENT; cnt ++)
{
ctx[cnt].state = IDLE_STATE;
ctx[cnt].num = cnt;
}
directory = opendir(argv[1]);
while((element = readdir(directory)) != NULL)
{
pthread_mutex_lock(&clientFreeMutex);
int cnt;
for (cnt = 0; cnt < MAX_CLIENT; cnt++)
{
if(ctx[cnt].state == IDLE_STATE)
{
ctx[cnt].filename = strdup(element->d_name);
ctx[cnt].state = BUSY_STATE;
pthread_create(&client[cnt], NULL, run, &(ctx[cnt]));
break;
}
}
/* No free client */
if (cnt == MAX_CLIENT)
{
printf("No free thread. Waiting.\n");
pthread_cond_wait(&clientFreeCond, &clientFreeMutex);
}
pthread_mutex_unlock(&clientFreeMutex);
}
closedir(directory);
exit(EXIT_SUCCESS);
}
問題是什么? 謝謝你的幫助 :)
警告您在單獨的線程中使用readdir的值,而沒有針對多線程的任何保護,因此(當您嘗試) printf client->file->d_name
您可能正在同時在主線程中執行readdir修改保存的結果,這具有不確定的行為。
例如,您需要在main中保存一個element->file->d_name
的strdup並將該字符串保存在clientCtx中,而不是struct dirent *
,當然還要在運行時將其釋放
請注意,即使在main的末尾,也沒有closedir ,即使這不是真正的問題(請記住其他程序)。
我終於找到了問題:啟動的線程沒有加入,pthread_create最后返回了一個錯誤代碼,錯誤信息設置為“無法分配內存”。 信號從未發送過,然后主線程被阻塞了。
我修復了此問題,為已啟動的線程創建了新狀態,並在主循環中添加了連接。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.