并发编程-进程(多道技术)

并发编程

并发与串行

  1. 什么是串行?

    串行就是程序自上而下,按顺序一行行执行程序,且必须把当前任务执行完毕才能执行下一个程序

    问题:

    • 程序执行效率变低
    • 占用内存资源
  2. 什么是并发?

    并发就是可以同时执行多个程序(本质是在不同的进程间快速切换执行,并保存程序状态) 总结就是:切换+保存

    串行和并发都是程序处理任务的方式

为什么要用并发?

  • 可以同时执行多个程序,提高了工作效率
  • 提高内存资源的利用率

实现并发的方式

  • 多进程
  • 多线程
  • 协程

什么是进程?

​ 进程指的是正在运行的程序,是操作系统调度以及进行资源分配的基本单位 (进程就是一个资源单位)

  1. 进程是怎么来的?

    当把一个程序从硬盘读入内存时,进程就产生了

  2. 什么是多进程?

    同一时间有多个程序被读入到内存并执行,就是多进程

进程来自于操作系统,有操作系统进行调度以及资源分配

多进程的实现原理其实就是操作系统调度进程的原理

多道技术 (重点)

实现原理:

  1. 空间复用:

    将内存划分多个区域,放入多个程序到内存中,且内存区域相互隔离(物理层面的隔离,为了保证数据安全)

  2. 时间复用:(切换+保存)

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

    切换任务的两种情况:

    • 当一个进程遇到了IO操作时会自动切换
    • 当一个任务执行时间超过阈值会强制切换

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

并发编程中的重要概念(重点)

  1. 串行:程序自上而下,按顺序一个个执行

  2. 并发:在不同的人物之间快速切换

  3. 并行:真正的同时执行多个程序,需要多核CPU

    三者都是处理任务的方式

  4. 阻塞: 指的是程序遇到了IO操作,无法继续执行代码时的一种状态

  5. 非阻塞:指的是程序没有遇到IO操作的一种状态

  6. 进程的三种状态

    • 阻塞:释放IO操作,转换成就绪
    • 运行:遇到IO操作和运行超时,转换成阻塞;释放IO操作转换成就绪
    • 就绪:CPU调用,转换成运行

python中使用多进程的两种方式:

  1. 导入 multiprocessing 中的Process类,实例化这个类,指定要执行的任务程序target

    import os
    from multiprocessing import Process
    """
    Process 就表示进程
    为什么要开进程
    """
    
    def task():
        print("this is sub process")
        print("sub process id %s" % os.getpid())
    
    
    if __name__ == '__main__':
        # ######注意 开启进程的代码必须放在 ————main————判断下面
        #  实例化一个进程对象 并制定他要做的事情  用函数来指定
        p = Process(target=task)
        p.start() # 给操作系统发送消息 让它开启进程
        print("this is parent process")
        print("parent process is: %s" % os.getpid())
        print("over")
    
  2. 导入 multiprocess 中的Process类,继承这个类,覆盖run方法,将要执行的任务放入到run中开启进程是会自动执行该函数

    from multiprocessing import Process
    import os
    
    
    class Downloader(Process):
    
        # def __init__(self,url,size,name):
        #     super().__init__()
        #     self.url = url
        #     self.size = size
        #     self.name = name
    
        def run(self):
            print(os.getpid())
            pass
    
    if __name__ == '__main__':
        m = Downloader()
        m.start()
        print("parent over",os.getpid())
    

join函数(重点)

主要能提高子进程的优先级,使得子进程执行完成后,在执行父进程

from multiprocessing import Process
import time
def task1(name):
    for i in range(10000):
        print("%s run" % name)

def task2(name):
    for i in range(100):
        print("%s run" % name)

if __name__ == '__main__': # args 是给子进程传递的参数 必须是元组
    p1 = Process(target=task1,args=("p1",))
    p1.start()  # 向操作系统发送指令
    # p1.join()   # 让主进程 等待子进程执行完毕在继续执行

    p2 = Process(target=task2,args=("p2",))
    p2.start()  # 向操作系统发送指令

    p2.join()  # 让主进程 等待子进程执行完毕在继续执行
    p1.join()


    #需要达到的效果是 必须保证两个子进程是并发执行的 并且 over一定是在所有任务执行完毕后执行
    print("over")

进程对象的常用属性 (了解)

 # p.daemon #守护进程
    # p.join()
    # print(p.exitcode) # 获取进程的退出码   就是exit()函数中传入的值
    # print(p.is_alive())  # 查看进程是否存活
    # print("zi",p.pid) # 获取进程id
    # print(os.getpid()) #获取当前进程的编号
    # p.terminate()  #终止进程  与strat 相同的是 不会立即终止,因为操作系统有很多事情要做  
    # print(p.is_alive()) 判断进程是否存活

僵尸进程和孤儿进程

孤儿进程 当父进程已经结束 而子进程还在运行 子进程就称为孤儿进程 尤其存在的必要性,没有不良影响

僵尸进程 当一个进程已经结束了但是,它仍然还有一些数据存在 此时称之为僵尸进程

在linux中,有这么一个机制,父进程无论什么时候都可以获取到子进程的的 一些数据

子进程 任务执行完毕后,确实结束了但是仍然保留一些数据 目的是为了让父进程能够获取这些信息

linux中 可以调用waitpid来是彻底清除子进程的残留信息

python中 已经封装了处理僵尸进程的操作 ,无需关心

posted @ 2019-08-02 08:26  raynduan  阅读(310)  评论(0编辑  收藏  举报