• python语法基础-并发编程-进程-进程理论和进程的开启


    ##############################################

    """
    并发编程的相关概念:
    
    进程
    1,运行中的程序,就是进程,程序是没有生命的实体,运行起来了就有生命了,
    操作系统可以管理进程,进程是操作系统基本的执行单元,
    2,每一个进程都有它自己的地址空间,进程之间是不会混的,比如qq不能访问微信的地址空间,
    操作系统替你隔离开了,这也是操作系统引入进程这个概念的原因,
    
    #######################################
    进程的调度
    1,先来先服务,有一个不好的,就是不利于短作业
    2,短作业优先算法,但其对长作业不利;不能保证紧迫性作业(进程)被及时处理;作业的长短只是被估算出来的。
    3,时间片轮转算法,就是轮流执行,已经很科学了,
    4,多级反馈队列算法,有多个队列,有一个新任务来了放入第一个队列,这是优先级加上时间片轮转,第二个任务来了放入下一级,
    
    #######################################
    并发和并行:
    进程的并行:这种只有在多核cpu才可以实现,
    进程的并发:这是轮流执行,由于速度很快,看起来像是一起执行的,比如一遍听音乐,一遍写代码,
    
    ######################################
    进程的三状态转换图:非常重要
    1,进程一开始运行的时候,是就绪的状态,这是第一个状态,就是告诉cpu,我已经准备好可以运行了,进入排队了,
    2,时间片轮转,轮到你了之后,你就运行了,这是第二个状态,
    3,发生阻塞,这是第三个状态,比如你的程序让你输入内容,input方法, 这时候是阻塞的,你输入完毕了之后,就又畅通了,
    这是等待I/O完成,input,sleep,文件的输入和输出,
    事件处理之后,你还要进入就绪状态了,
    全部处理完了,就结束了,
    
    ###########################################
    同步和异步
    1,同步,需要等待,需要排队,你什么也不能干,
    2,异步,不需要等待,你可以去做其他事情,
    
    ###########################################
    阻塞和非阻塞
    1,阻塞,就是input,sleep这些,需要等待,这是阻塞,
    2,非阻塞,就是跳过这些阻塞,但是程序中不可避免的需要阻塞,因为需要等待内容处理,
    
    ###########################################
    同步异步和阻塞非阻塞:
    同步阻塞,就是
    同步非阻塞
    异步阻塞
    异步非阻塞,效率更高,
    
    """

    ##############################################

    """
    Python中使用多进程
    
    运行中的程序就是一个进程。所有的进程都是通过它的父进程来创建的。
    因此,运行起来的python程序也是一个进程,那么我们也可以在程序中再创建进程。
    多个进程可以实现并发效果,就会让程序的执行速度变快。
    
    多进程有一个内置的模块,我们需要借助这个模块:
    from multiprocessing import Process
    
    """

    ##############################################

    """
    multiprocessing模块
    在这个包中几乎包含了和进程有关的所有子模块。由于提供的子模块非常多,为了方便大家归类记忆,
    我将这部分大致分为四个部分:
    1,创建进程部分,
    2,进程同步部分,
    3,进程池部分,
    4,进程之间数据共享。
    
    multiprocessing.Process介绍
    
    参数介绍
    #############
    Process([group [, target [, name [, args [, kwargs]]]]]),由该类实例化得到的对象,表示一个子进程中的任务(尚未启动)
    强调:
    1. 需要使用关键字的方式来指定参数
    2. args指定的为传给target函数的位置参数,是一个元组形式,必须有逗号
    参数介绍:
    1 group参数未使用,值始终为None
    2 target表示调用对象,即子进程要执行的任务
    3 args表示调用对象的位置参数元组,args=(1,2,'egon',)
    4 kwargs表示调用对象的字典,kwargs={'name':'egon','age':18}
    5 name为子进程的名称
    
    方法介绍
    ############
    1 p.start():启动进程,并调用该子进程中的p.run()
    2 p.run():进程启动时运行的方法,正是它去调用target指定的函数,我们自定义类的类中一定要实现该方法
    3 p.terminate():强制终止进程p,不会进行任何清理操作,如果p创建了子进程,该子进程就成了僵尸进程,
    使用该方法需要特别小心这种情况。如果p还保存了一个锁那么也将不会被释放,进而导致死锁
    4 p.is_alive():如果p仍然运行,返回True
    5 p.join([timeout]):主线程等待p终止(强调:是主线程处于等的状态,而p是处于运行的状态)。
    timeout是可选的超时时间,需要强调的是,p.join只能join住start开启的进程,而不能join住run开启的进程
    
    属性介绍
    ###############
    1 p.daemon:默认值为False,如果设为True,代表p为后台运行的守护进程,当p的父进程终止时,p也随之终止,并且设定为True后,
    p不能创建自己的新进程,必须在p.start()之前设置
    2 p.name:进程的名称
    3 p.pid:进程的pid
    4 p.exitcode:进程在运行时为None、如果为–N,表示被信号N结束(了解即可)
    5 p.authkey:进程的身份验证键,默认是由os.urandom()随机生成的32字符的字符串。
    这个键的用途是为涉及网络连接的底层进程间通信提供安全性,这类连接只有在具有相同的身份验证键时才能成功(了解即可)
    """

    ####################     进程的启动方式1             ############################

    创建单个进程,查看主进程id,父进程id,子进程id,

    注意参数的传递,args是传递一个元组,一个元素的时候要有逗号,kargs是传递一个字典,

    from multiprocessing import Process
    import time
    import os
    
    
    def task(name):
        print('{} is running!'.format(name))
        print('子进程id :', os.getpid(), '父进程id :', os.getppid())
        time.sleep(3)
        print('{} is done!'.format(name))
    
    
    # Windows开子进程要写在__name__==__main__下
    # 因为开子进程会重新加载父进程的内容
    if __name__ == '__main__':
        print('主进程id :', os.getpid())
        # 创建一个Python中的进程对象
        p = Process(target=task, args=('t1', ))  # 注册,这是主进程
        # p = Process(target=task, kwargs={'name': 't1'})
        p.start()  # 调用操作系统接口启动一个进程执行命令,这是子进程,
        # 现在子进程和主进程之间是异步的,如果我想在子进程结束之后再执行下面的代码,变成同步,怎么办?
        p.join()   # # 这个join就是在感知一个子进程的一个结束,将异步改成同步,
        # print("父进程的父进程号",os.getppid())  # 这个就是pycharm的进程号,
        print('--- 主进程 ----')  # 加上了join,这一句会在所有的子进程结束之后才会执行
    
    """
    没有加join:
    主进程id : 8560
    --- 主进程 ----
    t1 is running!
    子进程id : 9528  父进程id : 8560
    t1 is done!
    
    加了join:
    主进程id : 8592
    t1 is running!
    子进程id : 6448 父进程id : 8592
    t1 is done!
    --- 主进程 ----
    
    # 进程的生命周期,
    # 主进程没有开启子进程,就是执行完他的代码就结束了了
    # 子进程也是执行完自己的代码就结束了,
    # 开启了子进程的主进程,主进程执行完了,要等待子进程结束之后,主进程才可以结束,
    
    """

    创建多个进程:

    from multiprocessing import Process
    import time
    
    
    def task(name):
        print('{} is running!'.format(name))
        time.sleep(3)
        print('{} is done!'.format(name))
    
    
    if __name__ == '__main__':
        # 开启10个子进程
        p_list = []
        for i in range(10):
            p = Process(target=task, args=(i, ))
            p_list.append(p)
            p.start()
        # p.join()
        [p.join() for p in p_list]  # 保证前面的10个进程全部结束了,才会执行下面的代码,
        print('--- 主进程 ----')
        # 这种开启了多进程,可以读多个进程去存文件,取文件内容,

    #######################   进程的启动方式2       #########################

    # 进程的启动方式2
    # 第一点,创建一个类,继承process
    # 第二点,类中必须实现run方法,这个run方法里面就是子进程要执行的内容,
    import os
    from multiprocessing import Process
    
    class MyProcess(Process):  # 继承导入的process,
        def __init__(self,name):  # 为了进程能传递参数,
            super().__init__()  # 这是继承了父类所有的参数,
            self.name=name
        def run(self):
            # print(os.getpid())
            print("子进程号",self.pid)
            print("参数",self.name)  # print(os.getpid()) 这两句是一样的,
    
    
    if __name__ == '__main__':
        # p1=MyProcess()  # 这是不传参数的
        p1=MyProcess("name1")  # 这是传参数的,这就是面向对象的实例化,
        p2=MyProcess('name2')
        p3=MyProcess('name3')
    
        p1.start() #start会自动调用run
        p2.start()
        # p2.run()
        p3.start()
        # 三个进程之间是异步的,
    
        p1.join()
        p2.join()
        p3.join()
        # 三个进程都结束了才会执行下面的内容,这是把异步,变成异步,
        print('主线程')

    ###############   进程之间是数据隔离的    ##############

    # 进程之间的数据隔离问题
    # 进程和进程之间的数据是否是隔离的,比如qq和微信,之间的数据是隔离的,
    # 几个进程之间,如果不通过特殊的手段,是不可能共享一个数据的,这个记住,没有什么可理解的,
    
    # 下面是想了一个办法,去证明这个结论,但是这个结论你记住就行了,
    from multiprocessing import Process
    
    def work():
        global n  # 声明了一个全局变量,
        n=0
        print('子进程内: ',n)
    
    
    if __name__ == '__main__':
        n = 100
        p=Process(target=work)
        p.start()
        print('主进程内: ',n)

    ###############################################

    ################################################

  • 相关阅读:
    "gcc: cannot specify -o when generating multiple output files"解决方案
    VSCode 回退到上一层
    Mac下的clion配置c/c++环境
    安装homebrew报错error: Not a valid ref: refs/remotes/origin/master 的解决方法
    正则多个空格替换成一个空格 多个相同的字符值保留一个
    python for 循环的速度
    下载器
    requests content 和text 编码格式
    博客园积分排名
    python QQ 发送邮件功能
  • 原文地址:https://www.cnblogs.com/andy0816/p/12375624.html
Copyright © 2020-2023  润新知