深入分析父子线程、进程终止顺序不同产生的结果

Linux下编程,线程、进程退出顺序问题纷纷扰扰,如果父进程/线程先于子进程/线程终止,系统会做什么处理呢?反之,如果子进程/线程先于父进程/线程终止,系统又会做什么处理呢?下面是我个人平时在笔记上做的一些象征性的总结,如果有疑问之处,大可提出,我一直认为怀疑是人类进步的根本所在。

一、线程
Linux线程创建函数为pthread_create(),默认规则是谁创建子线程,谁就要负责子线程的资源回收,当父线程退出后,子线程也随着退出。所以,一般情况下,父线程退出时都要确保子线程已经退出,所以会使用pthread_join()函数阻塞等待子线程的退出信号/标识。
pthread_detach(threadid)函数的功能是使线程ID为threadid的线程处于分离状态(可以为非父子关系),一旦线程处于分离状态,该线程终止时底层资源立即被回收;否则终止子线程的状态会一直保存占用系统的资源直到主线程调用pthread_join(threadid,NULL)获取线程的退出状态。被创建的子线程也可以自己分离自己,子线程调用pthread_detach(pthread_self())就是分离自己,因为pthread_self()这个函数返回的就是自己本身的线程ID。
1)父线程先于子线程终止
父线程先于子线程,则子线程为异常退出 ,那肯定没有使用阻塞非分离函数pthread_join,分2种情况:
a)子线程已与父线程分离,如调用线程分离函数pthread_detach,则资源被自动回收释放。
b)子线程未与父线程分离,则资源无法释放,造成了资源浪费和系统臃肿(这种情况,我看有些资料上说系统也能自动释放子线程的资源,如关闭描述符,释放内存空间等等,但个人做过一些测试,比如在子线程中分配很多空间等,进程退出后,top查看内存状态时还存在)。
2)子线程先于父线程终止
也分2种情况:
a)正常情况:子线程调用了线程分离函数ptread_detach(),或父线程调用了等待线程结束函数pthread_join()。
 b)异常情况:如果上面二者都为调用,则为子线程分配的资源无法得到释放。

二、进程
一个现有进程可以调用fork函数创建一个新进程。由fork创建的新进程被称为子进程(child process)。fork函数被调用一次但返回两次。两次返回的唯一区别是子进程中返回0值而父进程中返回子进程ID。
1)父进程先于子进程终止
当父进程先退出时,系统会让init进程接管子进程,该子线程成为了孤儿进程。
2)子进程先于父进程终止
分为2种情况:
a)正常情况:父进程调用了wait函数 (非父子进程则用waitpid函数),此时父进程会等待子进程结束。
 b)父进程又没有调用wait函数 (非父子进程则未调用waitpid函数),此种情况子进程进入僵死状态即僵尸进程,并且会一直保持下去直到系统重启。子进程处于僵死状态时,内核只保存进程的一些必要信息以备父进程所需。此时子进程始终占有着资源,同时也减少了系统可以创建的最大进程数。
僵死状态:一个已经终止、但是其父进程尚未对其进行善后处理(获取终止子进程的有关信息,释放它仍占有的资源)的进程被称为僵死进程(zombie)。ps命令将僵死进程的状态打印为Z 。

(0)

相关推荐

  • C#实现终止正在执行的线程

    本文实例讲述了C#实现终止正在执行的线程的实现方法,并针对一些容易出错的地方进行了深入分析,具体方法如下: 一般来说,很多人都会使用Abort方法来终止线程,其实这种做法并不可取!如果你的线程正在操作临界资源,很有可能会造成资源没有正确释放而出现死锁问题.正确的做法应该是使用标记来终止线程的执行. 基本思路是:定义一个用于描述"停止"信号的变量,在整个程序启动前,设置该变量为false.在线程中,循环判断该变量是否已经被设置为true,如果没有,则继续执行,否则就退出循环并释放资源,然

  • Java中终止线程的三种方法

    Thread.stop, Thread.suspend, Thread.resume 和Runtime.runFinalizersOnExit 这些终止线程运行的方法已经被废弃,使用它们是极端不安全的! 1.线程正常执行完毕,正常结束 也就是让run方法执行完毕,该线程就会正常结束. 但有时候线程是永远无法结束的,比如while(true). 2.监视某些条件,结束线程的不间断运行 需要while()循环在某以特定条件下退出,最直接的办法就是设一个boolean标志,并通过设置这个标志来控制循环

  • 详解Java编程中线程的挂起、恢复和终止的方法

    有时,线程的挂起是很有用的.例如,一个独立的线程可以用来显示当日的时间.如果用户不希望用时钟,线程被挂起.在任何情形下,挂起线程是很简单的,一旦挂起,重新启动线程也是一件简单的事. 挂起,终止和恢复线程机制在Java 2和早期版本中有所不同.尽管你运用Java 2的途径编写代码,你仍需了解这些操作在早期Java环境下是如何完成的.例如,你也许需要更新或维护老的代码.你也需要了解为什么Java 2会有这样的变化.因为这些原因,下面内容描述了执行线程控制的原始方法,接着是Java 2的方法. Jav

  • Java终止循环体的具体实现

    编写程序,是先创建一个字符串数组,在使用foreach语句遍历时,如果发现数组中包含字符串"老鹰"则立刻中断循环.再创建一个整数类型的二维数组,使用双层foreach语句循环遍历,当发现第一个小于60的数组元素,则立刻中断整个双层循环,而不是内层循环. 复制代码 代码如下: public class Foreach {     public static void main(String[] args){         System.out.println("\n-----

  • 详解Java多线程编程中线程的启动、中断或终止操作

    线程启动: 1.start() 和 run()的区别说明 start() : 它的作用是启动一个新线程,新线程会执行相应的run()方法.start()不能被重复调用. run() : run()就和普通的成员方法一样,可以被重复调用.单独调用run()的话,会在当前线程中执行run(),而并不会启动新线程! 下面以代码来进行说明. class MyThread extends Thread{ public void run(){ ... } }; MyThread mythread = new

  • Python中用Ctrl+C终止多线程程序的问题解决

    复制代码 代码如下: #!/bin/env python # -*- coding: utf-8 -*- #filename: peartest.py import threading, signal is_exit = False def doStress(i, cc):     global is_exit     idx = i     while not is_exit:         if (idx < 10000000):             print "thread[

  • JAVA中 终止线程的方法介绍

    在Java的多线程编程中,java.lang.Thread类型包含了一些列的方法start(), stop(), stop(Throwable) and suspend(), destroy() and resume().通过这些方法,我们可以对线程进行方便的操作,但是这些方法中,只有start()方法得到了保留. 在Sun公司的一篇文章<Why are Thread.stop, Thread.suspend and Thread.resume Deprecated? >中详细讲解了舍弃这些方

  • 解析C/C++中如何终止线程的运行

    想要终止线程的运行,可以使用以下方法: 1.线程函数返回(最好使用该方法). 2.通过调用ExitThread函数,线程将自行撤消(最好不使用该方法). 3.同一个进程或另一个进程中的线程调用TerminateThread函数(应避免使用该方法). 4.ExitProcess和TerminateProcess函数也可以用来终止线程的运行(应避免使用该方法). 下面将详细介绍终止线程运行的方法:1-4,并说明线程终止运行时会出现何种情况:5. 1.线程函数返回 始终都应该将线程设计成这样的形式,即

  • Java并发编程示例(六):等待线程执行终止

    在某些场景下,我们必须等待线程执行完成才能进行下一步工作.例如,某些程序在开始执行之前,需要先初始化一些资源.这时,我们可以启动一个线程专门来做初始化任务,等到线程任务完成后,再去执行其他部分. 为此,Thread类为我们提供了join()方法.当我们使用线程对象调用此方法时,正在掉调用的线程对象将被推迟到被调用对象执行完成后再开始执行. 在本节,示例程序演示等待初始化方法完成后,再去执行其他任务. 知其然 按照下面所示步骤,完成示例程序. 1.创建一个名为DataSourcesLoader的类

  • c语言线程终止练习示例

    复制代码 代码如下: #include <stdio.h>#include <stdlib.h>#include <pthread.h> void *t1(void *args) { return (void *) 0;} void *t2(void *args) { printf("thread 2 param[args] = %d\n", args); pthread_exit((void *) 3);} void *t3(void *args)

随机推荐