我目前正在实现一个使用多线程但对总内存消耗有要求的应用程序。我想有一个主线程做 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”,线程成功地操纵了其父线程的堆栈。
我认为互联网上的大多数资源都没有正确表达这个事实。线程确实在共享内存的意义上共享堆栈,但每个线程的堆栈指针是私有的。对于每个线程,共享内存的一部分被分配为本地堆栈。
这也意味着父线程是否在堆栈上具有大型数据结构并不重要,因为内存永远不会为线程复制。