我目前正在实现一个使用多线程但对总内存消耗有要求的应用程序。我希望有一个主线程执行 I/O,并有几个工作线程执行计算。
目前,我在主堆栈上有几个可供工作人员访问的数据结构。我使用 OpenMP 进行工作分配。由于主/工作者模式不能很好地与 OpenMP 配合使用,我想使用 pthreads 进行多线程处理。
我知道每个线程都维护一个本地堆栈,但是在线程创建时堆栈到底会发生什么?
主线程堆栈上的数据结构是否可以被工作线程访问,或者我应该将它们移动到堆中?
我还想避免数据重复,但不知道新线程是否会创建主堆栈的本地副本。
编辑:我自己找到了答案......
在阅读了 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”,线程成功操作了其父线程的堆栈。
我认为互联网上的大多数资源都没有正确表达这一事实。
线程数do共享内存意义上的堆栈,但每个线程的堆栈指针是私有的。对于每个线程的一部分shared内存被分配为本地堆栈。
这也意味着父线程是否在堆栈上有大型数据结构并不重要,因为线程永远不会复制内存。