zoukankan      html  css  js  c++  java
  • 并发编程--多进程1

    并发编程-多进程

    多道技术

    实现原理:

    1.空间复用

    ​ 统一时间,加载多个任务到内存中,多个进程之间内存区域需要相互隔离,这种隔离是物理层面的隔离,其目的是为了保证数安全

    2.时间复用

    ​ 指的是,操作系统会在多个进程之间做切换执行

    ​ 切换任务的两种情况

    ​ 1.当一个进程遇到了IO操作 时会自动切换

    ​ 2.当一个任务执行时间超过阈值会强制切换

    ​ 注意:在切换前必须保存状态,以便后续恢复执行

    ​ 并且 频繁的切换其实也需要消耗资源

    ​ 当所有任务都没有IO操作时,切换执行效率反而降低,但是为了保证并发执行 必须牺牲效率

    简单的总结就是切换加保存

    有了多道技术,计算机就可以同时并发的处理多个任务

    串行

    自上而下运行

    并行

    真正的同时运行,必须具备多核CPU ,有几个核心就能并行几个任务,当任务数量超过核心数还是并发执行

    并发

    并发指的是多个任务同时被执行,并发编程指的是编写支持多任务并发的应用程序。

    进程

    进程指的是正在运行的程序,是一系列过程的统称,也是操作系统在调度和进行资源分配的基本单位

    进程是实现并发的一种方式

    一个程序可以产生多个进程

    PID和PPID

    PID:系统给进程的编号

    PPID:当一个进程a开启了另一个进程b,那么a被称为b的父进程。当pycharm运行了py文件,那么pycharm就是py文件的父进程

    并行与并发,阻塞与非阻塞

    并发指的是,多个事件同时发生了,需要一直切换完成

    并行指的是,多个事件同时进行,互不影响

    阻塞状态是因为程序遇到了IO操作,或是sleep,导致后续的代码不能被CPU执行

    非阻塞与之相反,表示程序正在被CPU执行。

    进程有三种状态,就绪态,运行态,阻塞态

    python中实现多进程

    python中开启子进程的两种方式

    方式1:实例化Process类

    from multiprocessing import Process
    import time
    
    def task(name):
        print(f'{name} is running ')
        time.sleep(3)
        print('f{name} is fone')
    if __name__=='__main__':
        #在windows系统之上,开启子进程的操作一定要放在这个里面
    	#Process(target=task,kwargs={'name':egon})
        p=Process(target=task,args=('jack',))#参数放在元祖里
    	p.start()	# 向操作系统发送请求,操作系统会申请内存空间,然后把父进程的数据拷贝给子进程,作为子进程的初始状态
        print('主')
        
    

    方式2:继承Process,并覆盖run方法

    from multiprocessing import Process
    import time
    
    class MyProcess(Process):
        def __init__(self,name):
            super(MyProcess,self).__init__()
            self.name=name
    
        def run(self):
            print('%s is running' %self.name)
            time.sleep(3)
            print('%s is done' %self.name)
    if __name__ == '__main__':
        p=MyProcess('jack')
        p.start()
        print('主')
    

    需要注意的是

    1.在windows下 开启子进程必须放到__main__下面,因为windows在开启子进程时会重新加载所有的代码造成递归创建进程

    2.第二种方式中,必须将要执行的代码放到run方法中,子进程只会执行run方法其他的一概不管

    3.start仅仅是给操作系统发送消息,而操作系统创建进程是要花费时间的,所以会有两种情况发送

    3.1开启进程速度慢于程序执行速度,先打印”主“ 在打印task中的消息

    3.2开启进程速度快于程序执行速度,先打印task中的消息,在打印”主“

    进程间内存相互隔离

    在一个进程内修改了全局变量,其他进程不受影响。就像是运行两个文件,一个修改了,另外一个不受影响。

    from multiprocessing import Process
    import time
    x=1000
    def task():
        global x
        x=0
        print('儿子死啦',x)
    
    
    if __name__ == '__main_
        print(x)
        p=Process(target=task)
        p.start()
        time.sleep(5)
        print(x)
        
    ###
    1000
    儿子死啦 0
    1000
    

    join函数:

    可以让一个进程等待另一个进程结束后再运行

    from multiprocessing import Process
    import time
    
    x=1000
    
    def task():
        time.sleep(3)
        global x
        x=0
        print('儿子死啦',x)
    if __name__ == '__main__':
        p=Process(target=task)
        p.start()
    
        p.join() # 让父亲在原地等,如果不加join函数,则会先执行print(x)
        print(x)
        
    
    from multiprocessing import Process
    import time,random
    
    x=1000
    
    def task(n):
        print('%s is runing' %n)
        time.sleep(n)
    
    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()
    
        p3.join() #3s
        p1.join()
        p2.join()
    
        print('主',(time.time() - start_time))
    
        start_time=time.time()
        p_l=[]
        for i in range(1,4):
            p=Process(target=task,args=(i,))
            p_l.append(p)
            p.start()
        for p in p_l:
            p.join()
        
        print('主',(time.time() - start_time))
    

    Process对象常用属性

    from multiprocessing import Process
    def task(n):
        print('%s is runing' %n)
        time.sleep(n)
    
    if __name__ == '__main__':
        start_time=time.time()
        p1=Process(target=task,args=(1,),name='任务1')
        p1.start() # 启动进程
        print(p1.pid) # 获取进程pid
        print(p1.name) # 获取进程名字
        p1.terminate() # 终止进程
        p1.join() # 提高优先级
        print(p1.is_alive()) # 获取进程的存活状态
        print('主')
    

    孤儿进程和僵尸进程

    孤儿进程:

    指的是开启子进程后,父进程先于子进程终止了,那这个子进程就称之为孤儿进程。

    孤儿进程是无害的,有其存在的必要性,在父进程结束后,其子进程会被操作系统接管。

    僵尸进程:

    指的是当父进程先结束,而父进程又没有回收子进程,释放子进程占用的资源,此时子进程会成为一个僵尸进程,这种情况只在linux下出现。因为windows中进程完全是独立的没有任何关联。

    如果父进程先退出,子进程被操作系统接管,子进程退出后操作系统会回收其占用的相关资源,

    python已经帮我们自动处理了僵尸进程的回收工作。

  • 相关阅读:
    简单项目却持着一颗纠结的心
    一个简单的打的系统
    ftqghkwiNdrpid快速建项Sql语句生
    3/21 Django框架 模板路径及模板过滤器 1.模板路径查找
    3/19 Django框架 url路由配置及模板渲染
    3/18 Django框架 启动django服务
    3/16 Django框架 环境搭建
    Windows子系统配置,cmder配置, pycharm配置django开发环境
    Requests+正则表达式抓取猫眼电影TOP100
    分析Ajax抓取今日头条街拍美图
  • 原文地址:https://www.cnblogs.com/zhoajiahao/p/11123327.html
Copyright © 2011-2022 走看看