• python 并发编程


    1.并发编程

    并发编程

      让你的程序可以同时处理多个任务(多道技术)

    什么是进程

    • 当程序在被操作系统运行的时候就是一个进程

    计算机发展史

      1.第一代计算机(1940-1955):真空管和穿孔卡片

      2.第二代计算机(1955-1965):晶体管和批处理系统

      3.第三代计算机(1965-1980):集成电路芯片和多道程序设计

      4.第四代计算机(1980-至今):个人计算机

    多道技术

    产生背景:想要在单个处理器的情况下实现多个进程并发的效果 实现原理:

    1. 空间上的复用性

      将内存分成多块,一次性读取多个程序

    2. 时间上的复用性 将进程执行时间进行切片,让处理器利用率提升到最大

    缺点:纯计算程序切换会降低效率,但是单核下必须切.

     

    并发与并行

      并发:  单个CPU,让进程看起来像同时进行(多道技术)

      并行:  多个CPU,多核,进程实际上就是在同时进行

    程序与进程的关系

    程序就是一堆代码 运行的程序的就是进程

    获取进程id

    • PID : 系统会给每个进程分配一个id,相当于人的身份证

    os.getpid()  # 获取自己的进程id
    • PPID : (parent PID)即父进程的id

    os.getppid()  # parent 获取父进程id

     

    阻塞和非阻塞:程序的状态(就绪 运行 阻塞)

    阻塞:   程序遇到IO操作或者sleep等需要等待的操作,导致后续代码不能被执行

    非阻塞:  非阻塞与阻塞相反,表示程序能被CPU正常运行

    • 程序运行的三状态

      • 运行 : 程序正在运行

      • 就绪 :当程序没有在阻塞状态时,就会进入就绪状态等待CPU执行

      • 阻塞:程序遇到IO或其他不需要用到CPU的操作时,就会进入阻塞

    2.python中实现并发

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

    # 第一种
    #---------------------------------------------------------------------------------------
    from multiprocessing import Process
    import os
    ​
    ​
    def task():
        print('self', os.getpid())
        print('parent', os.getppid())
        print('task run')
    ​
    ​
    # Windows创建子进程时, 子进程会将父进程的代码加载一遍, 导致重复创建子进程
    # 所以一定要将创建子进程的代码放在main下面
    ​
    ​
    if __name__ == '__main__':
        p = Process(target=task)  # 创建一个表示进程的对象,但并不是真正的创建进程
        p.start()  # 给操作系统发送通知,要求操作系统开启进程
        
        
    # 执行结果
    self 12636
    parent 11724
    task run
        
        
    #---------------------------------------------------------------------------------------    
    # 第二种
    #---------------------------------------------------------------------------------------
    # 创建子进程的第二种方式:继承Process  覆盖run方法  在子进程启动后自动执行run方法
    # 可以添加其他功能,不影响主进程
    class Myprocess(Process):
    ​
        def __init__(self, url):
            self.url = url
            super().__init__()
    ​
        def run(self):  # 子类方法只能定义为run,其他不能执行,如果要执行其他功能在run中调用
            print('下载文件...', self.url)
            print('run run run !')
    ​
    ​
    if __name__ == '__main__':
        p = Myprocess('www.baidu.com/a.mp4')
        p.start()
    ​
        
    # 执行结果
    下载文件... www.baidu.com/a.mp4
    run run run !
    python中开启进程的两种方式
       

    多个进程间的相互隔离

    • 即多个进程之间的内存空间是相互隔离的,数据增删查改互不影响

    a = 1000
    ​
    ​
    def task():
        global a
        # 修改子进程中的全局变量a,由于内存空间隔离,父进程中a任然是1000
        a = 0  
        print(id(a))
        print('子进程的a', a)
    ​
    ​
    if __name__ == '__main__':
        print(id(a))
        p = Process(target=task)
        p.start()
        print('父进程中的a',a)
        
    # 执行结果(父子进程中的a值和id都不同,说明空间相互隔离)    
    4697808
    父进程中的a 1000
    491482560
    子进程的a 0
    演示
     

    join()

    • join() : 提升绑定程序的优先级

    from multiprocessing import Process
    import time
    ​
    def task(i):
        print('我是%s号进程' % i)
        time.sleep(2)
    ​
    ​
    if __name__ == '__main__':
        start_time = time.time()
        ps = []
        for i in range(5):
            p = Process(target=task, args=(i, ))
            p.start()  # 开启5个子进程,执行过程无阻塞(子进程sleep是子进程的操作)
            ps.append(p)
    ​
        for p in ps:
            p.join()  # 子进程运行结束才会运行父进程,提升了子进程的优先级
    print(time.time()-start_time)
    ​
        print('over')
    ​
        
    # 执行结果
    我是1号进程
    我是2号进程
    我是0号进程
    我是3号进程
    我是4号进程
    2.3151323795318604
    over
    ​
    # 执行结果分析
    # 1.执行顺序混乱:由于子进程之间的优先级相同,操作系统随机执行
    # 2.结束总时间为什么是2秒多:由于for循环开启子进程无阻塞,所以时间极短,然后由于join绑定后子进程优先级高于父进程所以要等子进程运行完毕才执行父进程,所以总时间就是2秒加上for循环开启子进程时间.
    join方法演示

    进程的其他内置方法

    print(p.is_alive())  # 判断进程是否活着
    print(p.terminate())  # 终止这个进程
    ​
    p.daemon()  守护进程,守护的进程终止,守护进程也终止

    孤儿进程与僵尸进程

    孤儿进程: 没有parent的进程称为孤儿进程,parent进程终止后,子进程就变成孤儿进程了,无害 ​ 没有父进程,系统会自动回收

    僵尸进程: 子进程执行任务完毕后,但是还残留一些信息(id, 进程名),但是父进程没有处理这些 残留信息导致残留信息占用系统内存,有父进程,系统不会回收(有害) ​ 处理方法:终止父进程,使僵尸进程变成孤儿进程,被系统回收

  • 相关阅读:
    网页复制内容追加到剪切板
    windows安装 rabbitmq 快速避坑
    springboot rabbitmq快速入门上手(实用)
    python3 websocket客户端
    mybatis查询结果一对多
    mysql 插入数据,存在即更新
    centos7 安装mysql8.0
    收藏一个【fastjson反序列化漏洞原理及利用】
    .NET 5 with Dapr 初体验
    HttpClient缺陷引起的 无法连接到远程服务器 通常每个套接字地址只允许使用一次
  • 原文地址:https://www.cnblogs.com/liusijun113/p/10191768.html
Copyright © 2020-2023  润新知