pthread C中的池线程

时间:2019-02-21 19:46:00

标签: c multithreading operating-system threadpool

在我的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变量中定义的值一样,除非它在文件中找不到任何记录。但是现在,我必须使用线程池概念来做到这一点。因为我无法生成与文件中数据一样多的线程。

  

因此,我需要使用线程池来实现多线程。我做了   对其进行了一些搜索,但未获得任何许可。现在我   完全卡在这里,从哪里开始却一无所知   如何进行这项工作??

任何帮助将不胜感激。

3 个答案:

答案 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);

这里有两个主要错误:

  1. 创建线程后立即调用pthread_join。这意味着您等待线程完成。那么创建线程有什么意义呢?

  2. 一旦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.

我希望这会有所帮助。 但是您可以在这里进行多种方式和优化。