3.1 线程的基本概念及常见问题
提到线程,就不得不提到进程。一个进程代表计算机中实际运行的一个程序。在现代操作系统的保护模式下,每个进程都拥有自己独立的进程地址空间和上下文堆栈。但就一个程序本身执行的操作来说,进程其实什么也不做(不执行任何进程代码),只提供一个大环境容器,进程中的实际执行体是线程(thread)。因此在一个进程中至少得有一个线程,我们把这个线程称为“主线程”。
通俗地说,线程是进程中实际执行代码的最小单元,由操作系统安排调度(何时启动、运行、暂停及消亡)。
这里重点强调我们在实际开发中使用多线程时需要弄明白的问题。
3.1.1 主线程退出,支线程也将退出吗
在 Windows 系统中,当一个进程存在多个线程时,如果主线程执行结束,那么这时支线程(也可以叫工作线程)即使还没有执行完相关代码,也会退出。也就是说,主线程一旦退出,整个进程也就结束了。之所以强调这一点,是因为很多初学者经常在工作线程中写了很多逻辑代码,但没有注意到主线程已经提前退出,导致这些工作线程的代码来不及执行。解决这一问题的方案有很多,核心是让主线程不退出,或者主线程至少在工作线程完成工作之前不要退出。常见的解决方案有让主线程启动一个循环或者主线程等待工作线程退出后再退出。
在 Linux 系统中,如果主线程退出,则工作线程一般不会受到影响,还会继续运行,但此时这个进程就会变成僵尸进程。这是一种不好的做法,在实际开发中应该避免产生僵尸进程。
使用ps-ef 命令查看系统进程列表时,带有<defunct>字样的进程即僵尸进程:
Linux版本众多,在某些Linux版本的实现中,主线程退出也会导致支线程退出,这就和在 Windows 上的行为一样了。我们在实际开发中应以自己的机器测试结果为准。
3.1.2 某个线程崩溃,会导致进程退出吗
这是一道常见的面试题,还有一种问法是:进程中的某个线程崩溃,是否会对其他线程造成影响?
一般来说,每个线程都是独立执行的单位,都有自己的上下文堆栈,一个线程崩溃不会对其他线程造成影响。但是在通常情况下,一个线程崩溃也会导致整个进程退出。例如在Linux操作系统中可能会产生一个Segment Fault错误,这个错误会产生一个信号,操作系统对这个信号的默认处理就是结束进程,这样整个进程都被销毁,在这个进程中存在的其他线程自然也就不存在了。