• day34 并行并发、进程开启、僵尸及孤儿进程


    day34 并行并发、进程开启、僵尸及孤儿进程

    1、并行与并发

    什么是并行?

    并行指的是多个进程同时被执行,是真正意义上的同时

    什么是并发?

    并发指的是多个程序看上去被同时执行,这是因为cpu在多个程序之间不停的进行切换,且切换的速度十分快,让我们觉得自己在共享这段时间,所以不是真正意义上的同时

    2、阻塞与非阻塞

    阻塞:

    当程序在执行过程中遇到了IO操作,此时进入阻塞状态

    非阻塞:

    当程序正常执行代码而没有遇到IO操作时,此时就是非阻塞状态

    3、程序执行的三种状态

    在程序执行过程中,程序不是一直在执行的,那么程序在什么时候进行切换呢?

    CPU切换一般分为两种情况:

    • 程序需要进行IO操作,程序进入阻塞状态,CPU切换执行其他程序

    • 程序执行时间过长,其时间片消耗完,CPU 切换执行其他程序

    程序在执行过程中是在三种状态之间不停的进行切换

    这三种状态分别是:执行态、就绪态、阻塞态

    程序在被CPU执行时,进入执行态,当程序进行IO操作时,CPU切换执行其他程序,此时程序进入阻塞态,当程序的IO操作完成后,CPU不会立马执行这个程序,而是程序进入就绪态,等待CPU的执行;当然CPU还有另一种切换的情况既程序执行时间过长,此时程序没有进入阻塞态,而是直接进入就绪态,等待被CPU 执行

    4、开启进程的方法

    进程的开启与关闭时由操作系统进行的,那么我们如何开启进程呢?

    我们在开启进程时,实际上不是在开启进程,而是给系统发起一个指令,操作系统再根据我们的指令开启进程,所以有时我们在开启进程的过程中会发现,虽然发起了进程开启的指令,但是还是会一小段时间后才能开启成功

    开启进程的两种方式:

    直接将子进程执行的代码作为参数传入开启的子进程

    from  multiprocessing import Process
    def test(name):
        print("子进程开启")
        print(name)
        print("子进程结束")
    ​
    if __name__ == "__main__":
        print("父进程开启")
        print(os.getpid())
        p = Process(target=test,args=("lee",))
        p.start()
        print("父进程结束")
        
    # 执行结果
    # 父进程开启
    # 13254
    # 父进程结束
    # 子进程开启
    # lee
    # 子进程结束

    这种方式将需要执行的代码直接作为参数传递给子进程,除此之外,还有另一种方法可以将需要子进程执行的代码传递给子进程,那就是利用Process类将需要执行的代码直接写入到自己写的Process的子类中

    在上面的代码中可以看到Process是一个类,那么我们就可以直接继承自Process类,重写其run方法就可以使子进程执行相应的程序

    继承Process方法重写其run方法开启子进程

    from multiprocessing import Process
    ​
    class MyProcess(Process):
        def __init__(self, name):
            super().__init__()
            self.name = name
    ​
        def run(self):
            print("子进程开启")
            print(self.name)
            print("子进程结束")
    ​
    ​
    if __name__ == "__main__":
        print("父进程开启")
        p = MyProcess(name="rose")
        p.start()
        print("父进程结束")
        
    # 执行结果
    #父进程开启
    # 父进程结束
    # 子进程开启
    # rose
    # 子进程结束

    5、在Windows及liunx中使用开启多进程的不同之处

    在使用子进程执行程序时,子进程会首先copy父进程的部分数据,然后再将父进程的代码导入到子进程中,此时如果不将父进程放入if __name__ == __main__中就会出现递归导入,导致程序报错

    但是在Linux中,开启的子进程会完全复制父进程的代码及记录运行状态,然后再进行执行,所以不会形成递归调用

    当我们将程序交给子进程进行运行时,此时父进程与子进程之间的数据就是完全独立的两份,父进程的执行不会影响子进程中的变量,子进程的运行也不会影响父进程的变量

    6、join方法

    在使用父进程开启了子进程后,如果父进程的执行需要等到子进程的执行结果,那么就需要让父进程等待子进程的执行,但是当父进程执行较快时,子进程的执行还没有完成,父进程就会结束,此时需要让父进程等待子进程的执行,此时就需要使用join方法,join的作用就是提高子进程的优先级,使其执行完毕后才执行父进程

    from multiprocessing import Process
    ​
     def run(name):
        print("子进程开启")
        print(name)
        print("子进程结束")
    ​
    if __name__  == "__main__":
        print("父进程开启")
        p = Process(target=run,args=("lee",))
        p.start()
        p.join()
        print("父进程结束")
        
    # 运行结果
    # 父进程开始
    # 子进程开始
    # lee
    # 子进程结束
    # 父进程结束

     

    7、多进程中的其它方法

    name:进程的名字,在实例化进程对象时可以进行制定,如果不指定显示的是Process-编号的形式

    is_alive():判断子进程是否仍存活

    terminate():直接将子进程结束(杀死子进程)

    pid:显示子进程的进程编号

    8、pid与ppid

    pid:进程编号,指的是当前进程的进程号

    ppid:父进程编号,指的是当前进程的父进程的进程编号

     

    9、僵尸进程与孤儿进程

    僵尸进程:

    当子进程执行结束而父进程还没有结束时,系统会将子进程的资源进行回收,但是由于父进程需要查询子进程的进程号等信息,所以不会将子进程的进程描述符清除,此时如果父进程不使用wait()或waitpid()查询子进程,那么子进程会一直存在,产生僵尸进程,如果僵尸进程过多,那么就会占用系统的pid号,影响其他程序使用,不过在python中会对僵尸进程进行处理,不需要我们手动进行处理

    孤儿进程:

    当父进程已经结束,而子进程还没有结束时,这时候子进程就称之为孤儿进程,孤儿进程会交给系统进行处理,孤儿进程没有危害

     

  • 相关阅读:
    调研《构建之法》指导下的历届作品
    需求分析与原型设计
    软件工程的实践项目课程的自我目标
    php 字符串的一些操作,以便记忆
    MOTT的学习(一)
    session,cookie
    php Curl_setop 的学习
    使用Git进行代码管理的心得
    搭建andiord sdk和安装eclipse adt插件的个人小体会
    这些天自身努力的体会,关于java方面的
  • 原文地址:https://www.cnblogs.com/lice-blog/p/10957453.html
Copyright © 2020-2023  润新知