访问 linux 线程的本地堆栈(pthreads)
Posted
技术标签:
【中文标题】访问 linux 线程的本地堆栈(pthreads)【英文标题】:Access local stack of linux threads (pthreads) 【发布时间】:2013-09-23 16:08:09 【问题描述】:我目前正在实现一个使用多线程但对总内存消耗有要求的应用程序。我想有一个主线程做 I/O 和几个工人做计算。
目前,我在主堆栈上有几个数据结构可供工作人员访问。我使用 OpenMP 进行工作分配。由于主/从模式不适用于 OpenMP,我想使用 pthread 进行多线程。
我知道每个线程都维护一个本地堆栈,但是在创建线程时堆栈到底会发生什么?
工作人员是否可以访问位于主堆栈上的数据结构,或者我应该将它们移到堆中吗? 我也想避免数据重复,但不知道新线程是否会创建主堆栈的本地副本。
编辑:自己找到答案...
在阅读 pthreads 使用的 clone() 系统调用的详细信息后,我意识到所有线程共享完整的虚拟内存。这意味着尽管线程使用自己的堆栈,但用于每个堆栈的内存区域仍然是共享的。
我写了一些代码来验证这种行为:
#include <stdio.h>
#include <pthread.h>
void* increment(void* value)
int* val = (int*) value;
for(int i = 0; i < 100; i++)
++(*val);
return 0;
int main(int argc, char** argv)
int stackvar = 0;
pthread_t thread1, thread2;
int iret1, iret2;
iret1 = pthread_create( &thread1, NULL, increment, (void*) &stackvar );
iret2 = pthread_create( &thread2, NULL, increment, (void*) &stackvar );
pthread_join( thread1, NULL );
pthread_join( thread2, NULL );
printf("%i\n", stackvar);
return 0;
当输出为“200”时,线程成功地操作了其父线程的堆栈。
我认为互联网上的大多数资源都没有正确表达这个事实。 线程确实在共享内存的意义上共享堆栈,但每个线程的堆栈指针是私有的。对于每个线程,共享内存的一部分被分配为本地堆栈。
这也意味着父线程在堆栈上是否有大型数据结构并不重要,因为线程永远不会复制内存。
【问题讨论】:
你是对的,我错了。如果您使用pthread_create
,每个线程将从新的单独堆栈开始,而不是从父堆栈的副本开始。您应该发布您的编辑作为答案。
【参考方案1】:
是的,正如您所解释的,您可以共享您的堆栈。但是,一般情况下,您不应该这样做,除非在少数特殊情况下。您的示例程序存在数据竞争,因此纯靠运气输出仅为 200(可能是因为您的操作系统实际上并没有安排子程序同时运行。)
共享堆栈确实有意义的一种特殊情况是,当父级创建一些有趣的数据结构,然后将其传递给访问该数据结构只读的子级时。 p>
除了数据竞争之外,在堆栈而不是堆上共享可能会出错。父进程可以从创建子线程的过程中返回,因此堆栈数据可能不会在子线程的生命周期内保持有效。因此,您应该仅在 pthread_create()
调用和匹配的 pthread_join()
调用在同一范围内时共享堆栈数据(就像它们在您的示例中一样。)
【讨论】:
在我的场景中,我希望在父堆栈上有一个工作队列,并且线程将在创建工作队列的同一范围内加入。对队列的访问将被同步。我想这很好。以上是关于访问 linux 线程的本地堆栈(pthreads)的主要内容,如果未能解决你的问题,请参考以下文章
linux下多线程之pthread_detach(pthread_self())