• Python-进程-进程池-原理


     进程

      资源集合,调度和分配资源,说到进程就不得不提到线程,线程和进程是密不可分,进程申请了资源,但真正使用资源的是线程,其实本质上类似面向对象的思想,面向对象把数据和数据的操作封装在一个类中,进程把资源和对资源的操作封装在进程中,其实进程本质上是对资源的封装,那就比对进程和线程的区别来认识进程:

      1. 进程是资源容器,真正使用资源的是线程,进程可以申请并拥有自己独立资源但线程不能,线程只能使用进程已有的资源

      2. 进程在CPU上执行体现在线程,一个进程至少有一个主线程,可以有0个或者多个子线程

      3. 从粒度角度看,进程粒度远远比线程大,进程粒度比线程小,也就是切换进程消耗远比线程切换大

      4. 线程是操作系统调度的最小单位,对于IO操作进程和线程差别不大,进程和线程都可以竞争CPU资源,归根到本质上是线程在竞争CPU资源

      5. 进程与进程之间是资源完全隔离,也就是说不可互相访问

    北门吹雪: http://www.cnblogs.com/2bjiujiu/

    Python进程模块  multiprocessing

      # 这个模块的接口和线程模块threading一致

    多进程实例过程:

      1. 实例进程

      2. 启动子进程

      3. 等待子进程结束

    import multiprocessing
    
    
    def add(end, name):
        total = 0
        for i in range(end+1):
            total += i
        print(name)
        return total
    
    
    if __name__ == '__main__':
        # 实例子进程
        ps = multiprocessing.Process(target=add, args=(100, "北门吹雪"), name="北门吹雪")
        # 启动子进程
        ps.start()
        # 等待子进程结束
        ps.join()
    

      

    进程池      Pool

      # 接口和线程池一致,可以获取进程状态,如子进程执行结果、否准备、是否执行成功、等待子进程执行完成

      1. 实例进程池,需要传递进程池数量

      2. 添加子进程到进程池中

      3. 先关闭Pool,禁止进程池再接收任务

      4. 等待进程池中进程完成

      6. 关闭进程池

    import multiprocessing
    
    
    def add(end, name, blog):
        total = 0
        for i in range(end+1):
            total += i
        print(name, total, blog)
        return total
    
    
    if __name__ == '__main__':
        # 实例子进程,和CPU数量一致
        ps_pool = multiprocessing.Pool(multiprocessing.cpu_count())
        # 提交任务,获得返回进程对象对象, 可在此提交多个进程
        r = ps_pool.apply_async(func=add, args=(100, "北门吹雪", "https://www.cnblogs.com/2bjiujiu/"))
        # 获取执行结果,状态信息
        print(r.get())
        # print(r.wait())
        print(r.ready())
        print(r.successful())
        # 关闭线程池
        ps_pool.close()
        # 等待子线程完成
        ps_pool.join()
    

      7. 进程池获取子进程状态

         执行结果    .get

         是否就绪    .ready

         是否执行成功  .successful

         等待子进程   .wait

      8. 进程池imap方法, 特点是进程函数名不变,改变的传递进去的参数,结果是进程返回的结果,有先后顺序

    import multiprocessing
    
    
    def add(info):
        end = info[0]
        name = info[1]
        blog = info[2]
        total = 0
        for i in range(end+1):
            total += i
        print(end, name, blog)
        return total
    
    
    if __name__ == '__main__':
        # 实例子进程,和CPU数量一致
        ps_pool = multiprocessing.Pool(multiprocessing.cpu_count())
    
        # imap方式
        info = [(100, "北门吹雪", "https://www.cnblogs.com/2bjiujiu/"), (200, "北门吹雪", "https://www.cnblogs.com/2bjiujiu/")]
        # imap方式
        for total in ps_pool.imap(add, info):
            print(total)
    

     北_门_吹_雪:http://www.cnblogs.com/2bjiujiu/ 

    进程之间通信机制

      # 本质上是通过共享内存块实现通信

      1. 多进程Queue

    import multiprocessing
    
    
    def add(ps_queue, end, name, blog):
        total = 0
        for i in range(end+1):
            total += i
        print(name, blog)
        ps_queue.put(total)
    
    
    if __name__ == '__main__':
        # 实例队列
        ps_queue = multiprocessing.Queue()
        # 实例子进程
        ps = multiprocessing.Process(target=add, args=(ps_queue, 100, "北门吹雪", "https://www.cnblogs.com/2bjiujiu/"), name="北门吹雪")
        # 启动子进程
        ps.start()
        # 等待子进程结束
        ps.join()
        # 从Queue中取值
        print(ps_queue.get())
    

      2. 管道  Pipe,只适于两个进程中通信,性能优于Queue

    import multiprocessing
    
    
    def add(phone_one, end, name, blog):
        total = 0
        for i in range(end+1):
            total += i
        print(name, blog)
        # 发送数据,当然也可以接收
        phone_one.send(total)
    
    
    if __name__ == '__main__':
        # 实例管道, 类似打电话
        phone_one, phone_two = multiprocessing.Pipe()
        
        # 实例子进程
        ps = multiprocessing.Process(target=add, args=(phone_one, 100, "北门吹雪", "https://www.cnblogs.com/2bjiujiu/"), name="北门吹雪")
        # 启动子进程
        ps.start()
        # 等待子进程结束
        ps.join()
        
        # Pipe中取值
        print(phone_two.recv())
    

      3. 共享内存  Manager 包含Python基本数据结构 

    import multiprocessing
    from multiprocessing import Manager
    
    
    def add(share_list, end, name, blog):
        total = 0
        for i in range(end+1):
            total += i
        print(name, blog)
        # 添加数据
        share_list.append(total)
        share_list.append(name)
        share_list.append(blog)
    
    
    if __name__ == '__main__':
        # 实例共享内存对象
        share_memory = multiprocessing.Manager()
        # 实例list数据类型,当然除了list包括Python基本数据结构
        share_list = share_memory.list()
    
        # 实例子进程
        ps = multiprocessing.Process(target=add, args=(share_list, 100, "北门吹雪", "https://www.cnblogs.com/2bjiujiu/"), name="北门吹雪")
        # 启动子进程
        ps.start()
        # 等待子进程结束
        ps.join()
    
        # 从共享对象中取值
        print(share_list)
    

     北_门_吹_雪:http://www.cnblogs.com/2bjiujiu/  

    计算机资源:

      1. 内存、磁盘、CPU、网卡这4个是计算机核心资源

      2. 资源是稀缺的,需要竞争计算机资源

      3. 进程操作系统调度分配资源的单位,每个应用至少有一个进程

      4. 进程是竞争计算机资源的单位,CPU可以在不同的应用程序中切换,这个时间非常短暂,宏观上是并行,这个理念在在单核上,多核CPU可以并行执行多个进程

      5. 进程调度最核心的功能,操作系统会有自己算法,决定进程是否挂起,进程和线程的切换开销非常大,将CPU资源消耗在进程和线程切换上,时间片,频繁切换和保存进程上下文消耗CPU资源

     北_门_吹_雪:http://www.cnblogs.com/2bjiujiu/

    经验:

      1. 进程和线程都能竞争CPU资源,并且线程包含在进程中,同时存在又同时消亡(这里说主进程和主线程),进程和线程边界不清晰,这让进程和线程概念更加难以理清

      2. 进程和线程在逻辑上由非常多的相似点,如实例方式、启动方式、堵塞方式、池的概念、锁的概念,线程更像缩小版进程,但不是进程,包含在进程中只能使用进程分配已经有的资源

      3. 进程与进程之间资源隔离,不可互相访问,线程之间只能访问各自进程中的资源,并不是广义上的可以互相访问资源

      4. 进程用面向对象的语义来说,把资源和对资源的操作封装在一个进程中

      5. 进程切换消耗远大于线程,但为何还是需要进程,因为进程很像静态资源,使用静态资源效率上远比动态资源来的效率高,一般进程数量和CPU总核心数一致,但还是需要考虑安全冗余,不要把所有CPU跑满

     北_门_吹_雪:http://www.cnblogs.com/2bjiujiu/

  • 相关阅读:
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    详解以太坊世界状态
    VDF 不是工作量证明
    以太坊:Go-Ethereum: 编译运行
    【转】理解分布式账本技术: 经济学视角
    Counterfactual 项目:广义的以太坊状态通道
    Solidity 安全:已知攻击方法和常见防御模式综合列表
    Verge 攻击解析
    以太坊区块链的轻客户端
  • 原文地址:https://www.cnblogs.com/2bjiujiu/p/9154966.html
Copyright © 2020-2023  润新知