在我的Advance OS工作中,我需要从文件中读取数据并将其分配给线程以进行进一步处理。
这是我的代码,用于从文件读取数据并将其传递给线程函数
int main() {
FILE *fp = fopen(fileName, "r");
char str_pass[80][MAX_CHAR];
if (fp == NULL){
printf("Could not open file");
return 1;
}
int i=0;
pthread_t thread[THREADS];
int rc;
for(int th=1; th<=THREADS; th++)
{
if(fgets(str_pass[i], MAX_CHAR, fp) != NULL){
//printf("Hello, Thread %d\n",i);
rc = pthread_create(&thread[i], NULL, create_thread, (void*)str_pass[i]);
pthread_join(thread[i],NULL);
if(rc)
{
printf("ERROR; return code from pthread_create() is %d\n",rc);
exit(-1);
}
pthread_join(thread[i],NULL);
i++;
}
else{
printf("End of File");
exit(0);
}
}
pthread_exit(NULL);
fclose(fp);
return 0;
}
这是我的线程代码;
void * create_thread(void *hash_string)
{
gen_combinations(hash_string);
//sleep(1);
pthread_exit(NULL);
return NULL;
}
这段代码可以正常工作,并且它正在创建线程,数量与我在THREADS
变量中定义的值一样,除非它在文件中找不到任何记录。但是现在,我必须使用线程池概念来做到这一点。因为我无法生成与文件中数据一样多的线程。
因此,我需要使用线程池来实现多线程。我做了 对其进行了一些搜索,但未获得任何许可。现在我 完全卡在这里,从哪里开始却一无所知 如何进行这项工作??
任何帮助将不胜感激。
答案 0 :(得分:2)
查找“生产者/消费者问题”(如果您还不熟悉的话),尤其是多个消费者之间的差异。您的主线程扮演生产者的角色,从输入文件中读取数据和参数,并将它们打包为整洁的工作单元-这些是正在生成的小部件。工作者线程扮演着消费者的角色,接受工作单元并通过实际执行所描述的工作来“消费”它们。那是一个线程池。
您的特定实现可能不需要通用。可以对其进行适当的设计和调整,以专门解决当前的问题。
答案 1 :(得分:1)
rc = pthread_create(&thread[i], NULL, create_thread, (void*)str_pass[i]);
pthread_join(thread[i],NULL);
if(rc)
{
printf("ERROR; return code from pthread_create() is %d\n",rc);
exit(-1);
}
pthread_join(thread[i],NULL);
这里有两个主要错误:
创建线程后立即调用pthread_join
。这意味着您等待线程完成。那么创建线程有什么意义呢?
一旦pthread_join
返回,则该线程不再存在,并且其ID现在无效。但是,您再次调用pthread_join
,并将以前是ID的东西传递给了它,现在又把它传递给了它。这样做的后果是完全不可预测的。
答案 2 :(得分:1)
在您的示例中,您一次仅激活一个线程。您启动它,等到它结束,然后再从文件中读取下一行。这是由创建线程之后的pthread_join引起的。相反,您需要将join
语句移出循环以加入您创建的所有线程。
现在,您可以限制线程数,而无需创建池。您只需要一个原子计数器,该计数器将在线程启动之前增加,并在线程完成时减少。这样,您可以在创建下一个线程并等待条件变量之前检查计数器的值。这将是一种信号量。
示意图如下:
counter = 0;
while {
lock counter;
while (counter > 8)
wait_on_conditional_variable
counter ++;
unlock counter;
run thread;
}
join all remaining threads.
在线程中
do work;
lock counter;
counter --;
signal cond var;
unlock counter;
return;
对于池,您需要启动多个线程。每个线程都有一个循环,在其中等待某些作业可用。最有可能从fifo获得它。它必须等待条件变量来检查。
thread
do {
lock fifo;
while (fifo.size == 0)
wait on conditional variable.
read job from fifo;
unlock fifo;
do work;
} while (!exiting);
在读取文件时,应完成以下操作
while ... {
lock fifo;
push line into fifo;
signal var;
unlock fifo;
}
set-exit-condition;
join the pools.
我希望这会有所帮助。 但是您可以在这里进行多种方式和优化。