如何使用pthread管理c中的多个线程?

如何使用pthread管理c中的多个线程?,c,parallel-processing,pthreads,C,Parallel Processing,Pthreads,我正在尝试编写一个程序,该程序可以根据内核数扩展到使用动态数量的pthread来并行化一个简单的算法。该算法很简单,它采用整数输入数组,如果每个位置为%10!=0它将0存储在相应的输出数组位置,否则将存储10。我认为问题不存在,因为这是一个如此简单的问题。。。但我不明白为什么这不起作用: /*This variable is our reference to the child threads */ pthread_t childThreads[threadCount]; /* ...othe

我正在尝试编写一个程序,该程序可以根据内核数扩展到使用动态数量的pthread来并行化一个简单的算法。该算法很简单,它采用整数输入数组,如果每个位置为%10!=0它将0存储在相应的输出数组位置,否则将存储10。我认为问题不存在,因为这是一个如此简单的问题。。。但我不明白为什么这不起作用:

/*This variable is our reference to the child threads */
pthread_t childThreads[threadCount];

/*
...other setup code to initialize the parameters...
*/


/* create child threads*/
for(int i = 0; i< threadCount; i++)
{
    printf("running_P...\n");
    if(pthread_create(&(childThreads[i]), NULL, runParallelAlgorithm, (void *) &(parallelDataPakages[i])))
    {
        fprintf(stderr, "Error creating thread\n");
        return 1;
    }
}
/* join child threads*/
for(int i = 0; i< threadCount; i++)
{
    if(pthread_join(childThreads[i], NULL))
    {
        fprintf(stderr, "Error joining thread\n");
        return 2;
    }
    printf("not_running_P...\n");
}
我尝试过寻找其他解决方案,但看起来大多数人都在尝试使用相同的pthread\u t变量来生成线程,而我有一个数组。。。但它似乎仍然未能加入?为什么?我试着把它缩减到只有相关的代码,但因为我可以提供更多的信息,如果必要的话

编辑:对不起,我没有提供足够的信息。实际的程序有将近200行,我并不想一开始就把它全部发布在这里。但是如果问题不在本节中,我不确定是什么导致了这个问题。鉴于这不是问题所在,我将用包含的代码链接一个要点。导致问题的实际连接在第140行,很抱歉,我无法确定具体是什么:


更新:
pthread_join()
函数返回一个等于
ESRCH
的int,在手册中被列为“找不到ID为thread的线程”。我使用相同的
childThreads[]
数组来创建和加入线程,并且使用相同的控制变量
threadCount
,该变量始终为4,因此我不明白为什么找不到线程id?我尝试添加一个
pthread_退出(NULL)语句,但它似乎仍然不起作用。。。有什么新的想法吗?

你在完全错误的地方寻找问题

根本原因是缓冲区溢出,如下所示:

        /*advance the element pointer*/
        inputPointer = inputPointer + (sizeof(int) * elementsToProcess[i]);
        outputPointer = outputPointer + (sizeof(int) * elementsToProcess[i]);
您想通过
elementsToProcess[i]
来升级
int*inputPointer
int*outputPointer
。与
int
的大小相乘是完全错误的:指针的递增或递减会根据指向类型的大小更改地址,以便在数组中指向下一个或上一个元素。所以,应该是这样

        inputPointer = inputPointer + elementsToProcess[i];
        outputPointer = outputPointer + elementsToProcess[i];
或者更好

        inputPointer += elementsToProcess[i];
        outputPointer += elementsToProcess[i];

本质上,您的代码是在其他数据上涂鸦的,包括
childThreads[]
和C库内部分配元数据。

使用
pthread\u t
数组非常好,而且您似乎做得很正确。请给出一个-,这是我们常见的调试问题的标准,比如这个问题。我认为这将澄清问题出在您的代码的某些部分,而不是您到目前为止提供的片段中。您至少可以检查
pthread\u join
的返回错误代码,看看它失败的原因,这可能会提供一些提示。列出了可能的错误代码。很抱歉,我错发了错误号,现已修复该注释。Errno(error number的缩写)是一个系统错误代码,许多函数都会遵守它。一个常见的范例是“on error,函数返回-1并将errno设置为错误代码”。提供了有关函数失败原因的更多信息。但在本例中,
pthread\u join
只是返回一个错误代码,看起来根本不像是写入errno@Firestar9114,MCVE并不意味着发布整个程序。这意味着发布最小的完整程序,你可以拿出相同的问题。您可以通过从原始文件中删除所有不必要的内容或从头编写一个新的类似程序来准备这样的内容。无论哪种方式,都要确保结果显示出相同的问题。同样要注意的是,在制作MCVE的过程中,引导您自己发现问题的根源并不罕见。在任何情况下,不,在外部网站上链接到您的程序都不能替代问题中呈现的MCVE。哦!我懂了!我不知道它是否自动调整了类型,我认为它应该是pthreads中的某个东西,因为当我删除线程函数时,它就工作了。谢谢你指出这一点!此时,我仍在一行一行地检查,试图找出它不起作用的原因。:)为什么缓冲区溢出会阻止线程加入呢?pthread在遇到错误(如溢出)时是否不退出?@Firestar9114重写缓冲区是C中调用的许多方法之一。在你做了这样一件事之后,任何事情都可能发生,试图理解程序在那之后的行为是毫无意义的。在这种情况下,缓冲区后挤压的内存会出现线程连接错误。如果使用不同的编译器标志重新编译,则可能会得到segfault。如果你在你朋友的机器上运行它,它可能看起来工作得很好。一旦你调用UB,所有的赌注都被取消。@Firestar9114:yano说的;在编译时(
-O2
-Os
、或
-O0
)或体系结构(x86、x86-64、ARM等)更改优化级别时,故障模式确实会发生变化,因此知道“oops,
输出指针
最终指向错误的东西,在全局变量上乱涂乱画”就足够了。这是不值得的努力,试图二次猜测任何进一步,因为没有什么可以学习的。
        inputPointer += elementsToProcess[i];
        outputPointer += elementsToProcess[i];