主线程退出后线程访问共享变量

Posted

技术标签:

【中文标题】主线程退出后线程访问共享变量【英文标题】:thread access shared variables after main thread exit 【发布时间】:2015-06-07 23:47:59 【问题描述】:

如果分离线程在调用线程退出后访问共享变量(例如全局变量)并破坏共享变量,在多线程 C++ 程序中会发生什么?

class A 
 public:
  A()  printf("Constructing A\n"); 
  ~A()  printf("Destructing A\n"); 
  void printSomething()  printf("A is printing\n"); 


A a;

void thread_func() 
  printf("begin thread.\n");
  sleep(3); // make sure main thread exit first
  a.printSomething();
  printf("ending thread");


int main(int argc, char** argv) 
  std::thread t(thread_func);
  t.detach();

  return 0;

程序产生:

bash$ ./a.out
Constructing A
Destructing A
bash$

似乎主线程创建了全局变量 a 并在退出时将其销毁。那么如果分离的子线程尝试访问这个全局变量,3秒后会发生什么?

另一个困惑是,为什么主线程退出时会清除所有资源?好像全局变量的生命周期只依赖于主线程?

【问题讨论】:

当主线程退出时,它也会破坏 t。如果你想让某些东西比 main 更长寿,请使用 fork。 线程函数中的printf() 语句在哪里? printf() 语句并不是每次都在shell中输出。有时它会打印出“开始线程”。我认为这取决于两个线程的调度顺序。 【参考方案1】:

main() 返回或任何线程调用exit()_exit() 时,进程退出。

但是,main() 可以调用 pthread_exit() - 这将不会终止进程。根据 Linux pthread_exit() man page:

当一个线程终止时,进程共享的资源(例如,互斥锁、 条件变量、信号量和文件描述符)不是 释放,并且使用 atexit(3) 注册的函数不会被调用。

进程中的最后一个线程终止后,进程终止 就像调用退出状态为零的 exit(3) 一样;因此, 进程共享资源被释放,函数注册使用 atexit(3) 被调用。

【讨论】:

【参考方案2】:

线程本身没有自己的内存,但与它们的父进程共享内存。他们与父母联系在一起;因此,每当父母死亡时,它的子线程也会被杀死。

【讨论】:

即使child脱离了,在主线程退出时也会被kill掉? 所以分离一个线程并不会从它的父级移除它的依赖。当你分离一个线程时,它的父级不再需要杀死它来清理资源。分离的线程一旦退出,就会自动清理它们的内存,而不是要求父级pthread_join它们。根据定义,线程不能作为它们自己的实体存在。它们必须是流程的一部分。

以上是关于主线程退出后线程访问共享变量的主要内容,如果未能解决你的问题,请参考以下文章

java多线程2.线程安全之可见性

volatile 作用

从主循环访问线程变量 - c++ - windows

Delphi多线程访问公共变量,可以吗

多线程之内存可见性

再次理解多线程线程安全问题(理解java内存模型后)