python之路---并发编程之进程&僵尸进程/孤儿进程/守护进程

僵尸进程

子进程在结束之后,释放掉其占用的绝大部分内存空间以及cpu等资源,但是会留下一个称为僵尸进程的数据结构(包含子进程的pid),等待父进程处理。这种情况下的僵尸进程是无害的(待所有的子进程结束后,父进程会统一向操作系统发送回收子进程pid的请求,或者使用join(),其内部也拥有wait()方法),但是,如果父进程是一个死循环,不断的创造子进程,而又不发送回收请求,这就造成了大量的pid被占用

孤儿进程

在子进程结束之前,父进程就挂掉了,该子进程称之为孤儿进程(无害),最后会由所有进程的父进程进行发送回收请求(linux中为init进程) 

守护进程

两个关键词:守护/进程

进程:其本质也是一种“子进程”

守护:伴随的意思

即,守护进程会伴随着父进程代码的执行结束而死亡(彻彻底底,而非成为僵尸进程)

为什么要用守护进程

当该进程的代码在父进程的代码执行完毕后就没有存在的意义了,则应该将该进程设置为守护进程(例如在生产者与消费者模型中,生产者是专门负责产生数据的任务,而消费者是负责处理数据的任务,当生产者对象join之后,意味生产者不再生产数据,也意味着执行父进程的下一行代码,而消费者处理的数据来自生产者,所以应该将充当消费者的子进程设置为守护进程)

如何将进程设置为守护进程

import time
from multiprocessing import Process


def bar(name):
    print("%s is running" % name)
    time.sleep(3)
    print("%s is done" % name)


def foo(name):
    print("%s is running" % name)
    time.sleep(3)
    print("%s is done" % name)


if __name__ == '__main__':
    p1 = Process(target=bar, args=('守护进程',))
    p2 = Process(target=foo, args=('子进程',))
    p1.daemon = True  # 开启守护进程一定要在父进程发送请求之前
    p1.start()
    p2.start()
    print('主is done')

在这种情况下,执行结果可能有三种(取决于计算机的性能)

分析之前,首先要明确的是

1.start()操作只是代表父进程向操作系统发送创建子进程的请求(而非立即产生子进程),至于什么创建,先创建谁由操作系统决定

2.产生进程是需要开辟内存空间的,为子进程分配pid,通过导入的方式将父进程的代码复制到子进程中(还有其它资源),这些都是需要一定的时间

3.守护进程是伴随着父进程的代码执行完毕而结束(而非父进程的死亡)

4.print()操作,是先在内存中产生字符串这个对象,然后将其输出到屏幕上,这也是需要一定的时间

结果一

主进程is done
子进程 is running
子进程 is done

这是由于执行两个start()之后,立即执行了print()操作,待父进程代码执行完毕后,守护进程仍然没有被创造出来

结果二

主进程is done
守护进程 is running
子进程 is running
子进程 is done

这是由于,在父进程执行print()操作的时候,守护进程被创建出来

结果三

守护进程 is running
主进程is done
子进程 is running
子进程 is done

这是由于在父进程向操作系统发送申请子进程的时候,守护进程被创建出来

猜你喜欢

转载自blog.csdn.net/ltfdsy/article/details/82423064