• python_高级进阶(1)进程与并发


    进程与并发

    进程介绍:

    正在进行的一个过程或者说一个任务。而负责执行任务则是cpu

    进程的创建(两种方式)

    
    开启进程的第一种方式:
    from multiprocessing import Process
    import time
    
    def task(name):
        print(f'{name} is running')
        time.sleep(2)
        print(f'{name} is gone')
    
    
    
    if __name__ == '__main__':
        # 在windows环境下, 开启进程必须在 __name__ == '__main__' 下面
        p = Process(target=task,args=('SkyRabbit',))  # 创建一个进程对象
        p.start()  # 只是向操作系统发出一个开辟子进程的信号,然后就执行下一行了.
        这个信号操作系统接收到之后,会从内存中开辟一个子进程空间,然后在将主进程所有数据copy加载到子进程,然后在调用cpu去执行.
        开辟子进程开销是很大的.
        print('==主开始')
        time.sleep(3)
    
    
        所以永远会先执行主进程的代码.
    
    
    
    开启进程的第二种方式:
    
    from multiprocessing import Process
    import time
    
    class MyProcess(Process):
    
        def __init__(self,name):
            super().__init__()
            self.name = name
    
        def run1(self):
            print(f'{self.name} is running')
            time.sleep(2)
            print(f'{self.name} is gone')
    
    
    if __name__ == '__main__':
        p = MyProcess('SkyRabbit')
        p.start()
        print('===主')
    
    
    简单应用:
    
    
    from multiprocessing import Process
    import time
    #
    def task(name):
        print(f'{name} is running')
        time.sleep(1)
        print(f'{name} is gone')
    
    def task1(name):
        print(f'{name} is running')
        time.sleep(2)
        print(f'{name} is gone')
    
    def task2(name):
        print(f'{name} is running')
        time.sleep(3)
        print(f'{name} is gone')
    
    
    if __name__ == '__main__':
        # 在windows环境下, 开启进程必须在 __name__ == '__main__' 下面
        # p1 = Process(target=task,args=('SkyRabbit1',))  # 创建一个进程对象
        # p2 = Process(target=task,args=('SkyRabbit2',))  # 创建一个进程对象
        # 一个进程串行的执行三个任务
        start_time = time.time()
        task('SkyRabbit1')
        task1('SkyRabbit2')
        task2('SkyRabbit3')
        print(f'结束时间{time.time() - start_time}')
        三个进程 并发或者并行的执行三个任务
        start_time = time.time()
        p1 = Process(target=task, args=('SkyRabbit1',))  # 创建一个进程对象
        p2 = Process(target=task1, args=('SkyRabbit2',))  # 创建一个进程对象
        p1.start()
        p2.start()
        task2('SkyRabbit3')
        print(f'结束时间{time.time()-start_time}'
    
    
    

    获取进程pid

    
    import os
    import time
    print(f'子进程:{os.getpid()}')
    print(f'主(父)进程:{os.getppid()}')
    time.sleep(50)
    
    
    
    from multiprocessing import Process
    import time
    import os
    
    def task(name):
        print(f'子进程:{os.getpid()}')
        print(f'主进程:{os.getppid()}')
    
    
    
    if __name__ == '__main__':
        p = Process(target=task,args=('SkyRabbit',))  # 创建一个进程对象
        p.start()
        # print('==主开始')
        print(f'====主{os.getpid()}')
    
    

    验证进程之间的空间隔离

    
    from multiprocessing import Process
    import os
    import time
    name = 'SkyRabbit'
    
    def task():
        global name
        name = 'SkyRabbit_six'
        print(f'子进程{name}')
    
    
    if __name__ == '__main__':
        p = Process(target=task)  # 创建一个进程对象
        p.start()
        # print('==主开始')
        time.sleep(3)
        print(f'主:{name}')
    lst = ['SkyRabbit',]
    def task():
        lst.append('SkyRabbit_six')
        print(f'子进程{lst}')
    if __name__ == '__main__':
        p = Process(target=task)  # 创建一个进程对象
        p.start()
        # print('==主开始')
        time.sleep(3)
        print(f'主:{lst}')
    

    join让主进程等待子进程结束之后,在执行主进程.

    
    
    from multiprocessing import Process
    import time
    
    def task(name):
        print(f'{name} is running')
        time.sleep(2)
        print(f'{name} is gone')
    
    
    
    if __name__ == '__main__':
    
        p = Process(target=task,args=('SkyRabbit',))  # 创建一个进程对象
        p.start()
        p.join()
        print('==主开始')
    
    
    # 多个子进程使用join
    
    from multiprocessing import Process
    import time
    
    def task(name,sec):
        print(f'{name}is running')
        time.sleep(sec)
        print(f'{name} is gone')
    
    
    if __name__ == '__main__':
        start_time = time.time()
        p1 = Process(target=task,args=('SkyRabbit_one',1))
        p2 = Process(target=task,args=('SkyRabbit_two',2))
        p3 = Process(target=task,args=('SkyRabbit_three',3))
        p1.start()
        p2.start()
        p3.start()
        print(f'==主{time.time()-start_time}')  # 0.02 这只是主进程结束的时间,与其他进程毫无关系
    
    
    # 验证1
    
    from multiprocessing import Process
    import time
    
    def task(name,sec):
        print(f'{name}is running')
        time.sleep(sec)
        print(f'{name} is gone')
    
    
    if __name__ == '__main__':
        start_time = time.time()
        p1 = Process(target=task,args=('SkyRabbit',1))
        p2 = Process(target=task,args=('SkyRabbit_two',2))
        p3 = Process(target=task,args=('SkyRabbit_three',3))
    
        p1.start()
        p2.start()
        p3.start()
        # join 只针对主进程,如果join下面多次join 他是不阻塞的.
        p1.join()
        p2.join()
        p3.join()
    
        print(f'==主{time.time()-start_time}')
    
    #验证2
    
    from multiprocessing import Process
    import time
    
    def task(name,sec):
        print(f'{name}is running')
        time.sleep(sec)
        print(f'{name} is gone')
    
    
    if __name__ == '__main__':
        start_time = time.time()
        p1 = Process(target=task,args=('SkyRabbit',3))
        p2 = Process(target=task,args=('SkyRabbit_two',2))
        p3 = Process(target=task,args=('SkyRabbit_three',1))
    
        p1.start()
        p2.start()
        p3.start()
        # join就是阻塞
    
        p1.join()  # 等2s
        print(f'==主1:{time.time()-start_time}')
        p2.join()
        print(f'===主2:{time.time()-start_time}')
        p3.join()
        print(f'==主3:{time.time()-start_time}')  #
    
    
    #  优化上面的代码
    
    
    
    from multiprocessing import Process
    import time
    
    def task(sec):
        print(f'is running')
        time.sleep(sec)
        print(f' is gone')
    
    
    if __name__ == '__main__':
        start_time = time.time()
        p1 = Process(target=task,args=(1,))
        p2 = Process(target=task,args=(2,))
        p3 = Process(target=task,args=(3,))
    
        p1.start()
        p2.start()
        p3.start()
        # join 只针对主进程,如果join下面多次join 他是不阻塞的.
        p1.join()
        p2.join()
        p3.join()
    
    
    
        #正确示范:
        l1 = []
        for i in range(1, 4):
            p = Process(target=task,args=(i,))
            l1.append(p)
            p.start()
    
        for i in l1:
            i.join()
    
        print(f'==主{time.time()-start_time}')
    
        # join就是阻塞,主进程有join,主进程下面的代码一律不执行,直到进程执行完毕之后,在执行.
    
    
    

    守护进程:

    古时候 太监守护这个皇帝,如果皇帝驾崩了,太监直接也就死了.
    子进程守护着主进程,只要主进程结束,子进程跟着就结束,

    
    if __name__ == '__main__':
        # 在windows环境下, 开启进程必须在 __name__ == '__main__' 下面
        p = Process(target=task,args=('SkyRabbit',))  # 创建一个进程对象
        p.daemon = True  # 将p子进程设置成守护进程,只要主进程结束,守护进程马上结束.
        p.start()
        # p.daemon = True  # 一定要在子进程开启之前设置
        time.sleep(1)
        print('===主')
    
    

    进程的开启:

    一个子进程必须依赖主进程.
    一个主进程可以开启多个子进程.
    unix: fork创建子进程.
    unix(linux,mac): 创建一个子进程会完完全全复制一个主进程所有的资源,初始资源不变.
    windows: 操作系统调用CreateProcess 处理进程的创建.
    windows:创建一个子进程,会copy主进程所有的资源,但是会改变一些资源.

    进程与程序的区别

    程序仅仅只是一堆代码,进程是指程序的运行过程.

    进程的三种状态:

    运行,阻塞,就绪.

    并发与并行:

    并发:是伪并行,看起来同时运行,实际上就是单个cpu+多道技术,实现并发
    并行:同时运行,指具有多个cpu才能实现并行

    多道技术概念

    空间上的复用: 一个内存可以加载多个进程.

    时间上的复用: 当进程遇到IO阻塞,或者长时间运行,操作系统会将此进程挂起,
    保留状态,会将cpu强行的切换到另一个进程.

    串行:

    程序一个一个排队让cpu执行

    阻塞:

    cpu遇到IO就会阻塞.在原地等着任务结束,
    根本不考虑任务是在计算还是在io阻塞,
    总之就是一股脑地等任务结束
    复制代码

    非阻塞:

    指在不能立刻得到结果之前也会立刻返回,同时该函数不会阻塞当前线程。

  • 相关阅读:
    xshell,putty远程连接Linux并使用密钥认证
    配置IP
    认识linux
    dpkg: error processing package libraspberrypi-doc (--configure): package is in a very bad inconsistent state;
    pi4j,Netbeans中togglebutton跟Jbutton的区别
    Netbeans配置Java SE嵌入式平台(树莓派)
    发光二极管正负极判断
    Eclipse安装图形JFrame,Jswing编程界面
    阿里云Centos6.9安装图形化界面
    Oracle 一个中文汉字 占用几个字节,由Oracle中字符集编码决定
  • 原文地址:https://www.cnblogs.com/SkyRabbit/p/11383866.html
Copyright © 2020-2023  润新知