线程如何访问父线程的变量

Sha*_*dra 5 multithreading pthreads shared-memory

我读到线程共享它的父线程的内存地址空间.如果这是真的,为什么线程函数不能访问属于它的父线程的局部变量?

void* PrintVar(void* arg){
   printf( "%d\n", a);
}

int main(int argc, char*argv[]) {
   int a;
   a = 10;
   pthread_t thr;
   pthread_create( &thr, NULL, PrintVar, NULL );

}
Run Code Online (Sandbox Code Playgroud)

如果线程共享地址空间,那么PrintVar函数应该能够打印出来的值variable a吧?

我在http://www.yolinux.com/TUTORIALS/LinuxTutorialPosixThreads.html上阅读了这条信息.

同一进程中的线程共享:进程指令大多数数据打开文件(描述符)信号和信号处理程序当前工作目录用户和组ID

如果这是真的,那么为什么int a不能作为共享变量?

我想看一个共享文件描述符的示例代码

Jer*_*ner 8

子线程可以访问父线程堆栈中的变量,只需知道变量的地址即可.例如,你可以这样做:

void* PrintVar(void* arg){
   int * a = (int *) arg;
   printf( "%d\n", *a);
}

int main(int argc, char*argv[]) {
   int a;
   a = 10;
   pthread_t thr;
   pthread_create( &thr, NULL, PrintVar, &a );
}
Run Code Online (Sandbox Code Playgroud)

请注意,这种事情可能很棘手,因为您必须(以某种方式)保证(a)在子线程仍在访问它时不会被销毁.(在这种情况下,你可能想在main()的末尾调用pthread_join(),这样主线程就会阻塞而不会从main()返回,直到子线程退出为止)

  • 请注意,"共享地址空间"仅表示来自任一线程的给定指针值将引用相同的RAM物理字节.与两个不同进程的情况相反,其中每个进程可以保持具有相同值的指针,但是由于虚拟内存魔术,两个指针仍然指向两个不同的物理存储器位置. (2认同)

Sin*_*ion 5

即使这不是一个线程,你也不能这样做,因为 a 超出了范围。

将 a 放在全局范围内,如下所示:

int a;
void* PrintVar(void* arg){
   printf( "%d\n", a);
}

int main(int argc, char*argv[]) {
   a = 10;
   pthread_t thr;
   pthread_create( &thr, NULL, PrintVar, NULL );

}
Run Code Online (Sandbox Code Playgroud)

这实际上不是线程的问题。考虑以下代码:

void PrintVar(){
   printf( "%d\n", a);
}

int main(int argc, char*argv[]) {
   int a;
   a = 10;
   PrintVar();
}
Run Code Online (Sandbox Code Playgroud)

这显然行不通,因为在ainmain中声明的变量名在中不可见PrintVar,因为它在另一个块的本地范围内。这是一个编译时问题,编译器只是不知道您aPrintVar.

但还有另一个线程问题。当一个进程的主线程退出时,其他所有线程都被终止(具体来说,当任何线程调用时_exit,则所有线程都被终止,返回后_start调用)。但是您的主要在调用另一个线程后立即返回。为了防止这种情况,您应该调用which 将在返回之前等待线程退出。看起来像这样_exitmainpthread_join

int a;
void* PrintVar(void* arg){
   printf( "%d\n", a);
}

int main(int argc, char*argv[]) {
   void *dummy;
   a = 10;

   pthread_t thr;
   pthread_create( &thr, NULL, PrintVar, NULL );
   pthread_join( thr, &dummy);
}
Run Code Online (Sandbox Code Playgroud)