week6 day3 并发编程之多进程 理论

写应用程序的核心思想:
提高程序的运行速度,尽量长的将CPU握在当前进程手里面。减少IO操作,IO操作是耗时最久的网络IO。能从本地取数据就不从网络取数据,
能从内存取数据就不从硬盘取数据。

一、什么是进程?

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

举例(单核+多道,实现多个进程的并发执行):egon在一个时间段内有很多任务要做:python备课的任务,写书的任务,交女朋友的任务,王者荣耀上分的任务,但egon同一时刻只能做一个任务(cpu同一时间只能干一个活),如何才能玩出多个任务并发执行的效果?egon备一会课,再去跟李杰的女朋友聊聊天,再去打一会王者荣耀…这就保证了每个任务都在进行中。

二、进程与程序的区别

程序仅仅是一堆代码,而进程指的是程序的运行过程。

需要强调的是:同一个程序执行两次,那也是两个进程,比如打开暴风影音。虽然都是同一个软件,但是一个可以播放苍井空,一个可以播放饭岛爱。

三、并发与并行

无论是并发还是并行,在用户看来都是“同时运行”的,不管是进程还是线程,都只是一个任务而已,真正干活的是CPU,CPU来做这些任务,而一个CPU同一时刻只能执行一个任务。

3.1 并发:是伪并行,即看起来是同时运行。单个CPU+多道技术就可以实现并发

单CPU,多进程,并发举例:你是一个cpu,你同时谈了三个女朋友,每一个都可以是一个恋爱任务,你被这三个任务共享要玩出并发恋爱的效果,应该是你先跟女友1去看电影,看了一会说:不好,我要拉肚子,然后跑去跟第二个女友吃饭,吃了一会说:那啥,我去趟洗手间,然后跑去跟女友3开了个房。

单核下,可以利用多道技术,多个核,每个核也都可以利用多道技术(多道技术是针对单核而言的)。有四个核,六个任务,这样同一时间有四个任务被执行,假设分别分配给了CPU1、CPU2、CPU3、CPU4.一旦任务遇到IO就被迫中断执行,此时任务5就拿到了CPU1的时间片去执行,这就是单核下的多道技术。而一旦任务一的IO也结束了,操作系统会重新第哦啊用它(需知进程的调度、分配给哪个CPU执行、由操作系统说了算),可能被分配给四个CPU中的任意一个去执行。

3.2 并行:同时运行,只有具备多个CPU才能实现并行

3.3 多道技术

在这里插入图片描述
所有现代计算机经常会在同一时间做很多事,一个用户的PC(无论单CPU还是多CPU),都可以同时运行多个任务(一个任务可以理解成一个进程)。

启动一个进程来杀毒(360软件)

启动一个进程来看电影(暴风影音)

启动一个进程来聊天(腾讯QQ)

所有这些进程都需要被管理,于是一个支持多进程的多道程序系统是至关重要的。

多道技术概念回顾:内存中同时存入多道(多个)程序,CPU能从一个进程快速切换到另一个,使每个进程各自运行几十或几百毫秒,这样,虽然在同一个瞬间,一个CPU只能执行一个任务,但在一秒内,CPU却可以运行多个进程,这就给人一种并行的错觉,即伪并行,以此来区分多处理器的操作系统的真正硬件并行(多个CPU共享同一个物理内存)。

空间上的复用和时间上的复用

  1. 空间上的复用。多个而应用程序共用一套计算机硬件,包括硬盘、内存等。
  2. 时间上的复用。多道只需要任务时间最长的那个任务+切换进程的时间

切换+保存状态
切换CPU分为两种情况:

  1. 当一个程序遇到IO操作的时候,操作系统会剥夺该程序的CPU执行权限
    作用:提高了CPU的使用率,并且也不会影响程序的执行效率
  2. 当一个进程长时间占用CPU的时候,操作系统也会剥夺该程序的CPU执行权限
    作用:降低了程序的执行效率(原本的执行时间+切换时间)

四、同步/异步 and 阻塞/非阻塞(重点)

进程调度:

  • 先来先服务调度算法(发展历史)
    “对长作业有利,对短作业无益”
  • 短作业优先调度算法(发展历史)
    “对短作业有利,对长作业无益”
  • 时间片轮转法+多级反馈队列(见图)在这里插入图片描述

两对重要概念:

同步和异步:描述提交任务的两种方式


同步在发出一个功能调用之后,在没有得到结果之前,该调用不会返回。但是一般而言,我们在说同步、异步的时候,特指那些需要其他部件或者需要一定时间完成的任务。
#举例

  1. multiprocessing.Pool下的apply #发起同步调用后,就在原地等着任务结束,根本不考虑任务是在计算还是在io阻塞,总之就是一股脑地等任务结束
  2. concurrent.futures.ProcessPoolExecutor().submit(func,).result()
  3. concurrent.futures.ThreadPoolExecutor().submit(func,).result()

异步:异步概念与同步相对。当一个异步功能调用发出之后,调用者不能立刻得到结果。当该异步功能完成后,通过状态、通知、回调来通知调用者。如果该异步功能用状态来通知,那么调用者就需要隔一段时间回来检查一次,效率就很低;如果是通知的方式,效率则很高,因为异步功能几乎不需要做额外的操作。至于回调函数,其实和通知没多大区别。
#举例

  1. multiprocessing.Pool().apply_async() #发起异步调用后,并不会等待任务结束才返回,相反,会立即获取一个临时结果(并不是最终的结果,可能是封装好的一个对象)。
  2. concurrent.futures.ProcessPoolExecutor(3).submit(func,)
  3. concurrent.futures.ThreadPoolExecutor(3).submit(func,)

阻塞和非阻塞:描述的是程序的运行状态


阻塞:对应程序运行状态中的阻塞态。阻塞调用是指调用结果返回之前,当前线程会被挂起(如遇到IO操作)。函数只有在得到结果之后才会将阻塞的线程激活。有人也许会把阻塞调用和同步调用等同起来,实际上不是一样的。对于同步调用来说,很多时候当前线程还是激活的,只是从逻辑上当前函数没有返回而已。

  1. 同步调用:apply一个累计一亿次的任务,该调用会一直等待,直到任务返回结果为止,但并未阻塞住(即便是抢走CPU的执行权限,那也是一直处于就绪态);
  2. 阻塞调用:当socket工作在阻塞模式的时候,如果没有数据的情况下调用recv函数,则当前线程就会被挂起,直到有数据为止。

非阻塞:就绪态,运行态。指在不能立刻得到结果之前也会立刻返回,同时该函数不会阻塞当前进程。

总结:


  1. 提交任务的两种方式分为同步和异步。同步指的是当调用一个任务的时候,在任务执行完毕之前,调用者会在原地等待结果;异步指的当调用一个任务时,调用者不会原地等待运行结果,当调用结束后,会以通知、状态、回调的方式通知调用者。
  2. 程序的运行状态分为阻塞和非阻塞。阻塞态指的是当请求不能满足的时候就将进程挂起,而非阻塞态不会。

根据提交任务方式的不同和运行任务的状态不同。可以将上述概念分为四组,分别是同步阻塞、异步阻塞、同步非阻塞、异步非阻塞。最理想的运行状态是异步非阻塞。pycharm属于同步阻塞。

五、进程的创建(了解)

但凡是硬件,都需要有操作系统去管理,只要有操作系统,就有进程的概念,就需要有创建进程的方式,一些操作系统只会一个应用程序设计,比如微波炉的控制器,一旦启动微波炉,所有的进程都已经存在。

而对于通用的系统(跑很多程序),需要有系统运行过程中创建或撤销的能力,主要分为四种形式创建新的进程。

  1. 系统初始化(查看linux中用ps命令,Windows中用任务管理器,前台进程负责与用户交互,后台运行的进程与用户无关,运行在后台并且只在需要时才唤醒的进程称为守护进程,如电子邮件、web页面、新闻、打印)

  2. 一个进程在运行过程中开启了子进程(如nginx开启多线程,os.fork,subprocess,Popen等)

  3. 用户的交互式请求,而创建一个新进程(如双击暴风影音)

  4. 一个批处理作业的初始化(只在大型机的批处理系统中应用)

无论哪一种,新进程的创建都是由一个已经存在的进程执行了一个创建进程的系统调用而创建的:

  1. 在UNIX中该系统调用是:fork,fork会创建一个与父进程一模一样的副本,二者有相同的存储映像、同样的环境字符串和同样的打开文件(在shell解释器进程中,执行一个命令就会创建一个子进程)

  2. 在windows中该系统调用是:CreateProcess,CreateProcess既处理进程的创建,也负责把正确的程序装入新进程。

关于创建的子进程,UNIX和windows

  1. 相同的是:进程创建后,父进程和子进程有各自不同的地址空间(多道技术要求物理层面实现进程之间内存的隔离),任何一个进程的在其地址空间中的修改都不会影响到另外一个进程。

  2. 不同的是:在UNIX中,子进程的初始地址空间是父进程的一个副本,提示:子进程和父进程是可以有只读的共享内存区的。但是对于windows系统来说,从一开始父进程与子进程的地址空间就是不同的。

六、进程的终止(了解)

  1. 正常退出(自愿,如用户点击交互式页面的叉号,或程序执行完毕调用发起系统调用正常退出,在linux中用exit,在windows中用ExitProcess)

  2. 出错退出(自愿,python a.py中a.py不存在)

  3. 严重错误(非自愿,执行非法指令,如引用不存在的内存,1/0等,可以捕捉异常,try…except…)

  4. 被其他进程杀死(非自愿,如kill -9)

七、进程的层次结构

无论是windows还是unix,进程都只有一个父进程,不同的是:

  1. 在unix中所有的进程,都是以init进程为根,组成树形结构。父子进程共同组成一个进程组,这样,当从键盘发出一个信号的时候,该信号被送给键盘相关的进程组中的所有成员

  2. 在windows中,没有进程层次的概念,所有的进程都是地位相同的,唯一类似于进程层次的暗示,是在创建进程时,父进程会得到一个特别的令牌(称为句柄),该句柄可以用来控制子进程,但是父进程有权把该句柄传给其他子进程,这样就没有层次了。

八、进程的状态

在这里插入图片描述
其实两种情况下会导致一个进程在逻辑上不能运行

  1. 进程挂起是自身原因,遇到IO阻塞,便要让出CPU给其他进程去执行,这样保证CPU一直在工作

  2. 与进程无关,是操作系统层面,可能会因为一个进程占用时间过多,或者优先级等原因,而调用其他的进程去使用CPU

九、进程并发的实现(了解)

进程并发的实现在于,硬件中断一个正在执行的程序,把此事进程运行状态的所有状态保存下来,为此,操作系统维护一张表格,即进程表(process table),每个进程占用一个进程表项(这些进程也被称为进程控制块)。

在这里插入图片描述
该表存放了进程状态的重要信息:程序计数器、堆栈指针、内存分配状况、所有打开文件的状态、帐号和调度信息,以及其他在进程由运行态转为就绪态或阻塞态时,必须保存的信息,从而保证该进程在再次启动时,就像从未被中断过一样。

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值