Python之路(第三十六篇)并发编程:进程、同步异步、阻塞非阻塞

1、理论基础

 

进程的概念起源于操做系统,是操做系统最核心的概念,也是操做系统提供的最古老也是最重要的抽象概念之一。操做系统的其余全部内容都是围绕进程的概念展开的。html

即便能够利用的cpu只有一个(早期的计算机确实如此),也能保证支持(伪)并发的能力。将一个单独的cpu变成多个虚拟的cpu(多道技术:时间多路复用和空间多路复用+硬件上支持隔离),没有进程的抽象,现代计算机将不复存在。python

 

必备的理论基础:linux

  #一 操做系统的做用:
      1:隐藏丑陋复杂的硬件接口,提供良好的抽象接口
      2:管理、调度进程,而且将多个进程对硬件的竞争变得有序
  ​
  #二 多道技术:
      1.产生背景:针对单核,实现并发
      ps:
      如今的主机通常是多核,那么每一个核都会利用多道技术
      有4个cpu,运行于cpu1的某个程序遇到io阻塞,会等到io结束再从新调度,会被调度到4个
      cpu中的任意一个,具体由操做系统调度算法决定。
      
      2.空间上的复用:如内存中同时有多道程序
      3.时间上的复用:复用一个cpu的时间片
         强调:遇到io切,占用cpu时间过长也切,核心在于切以前将进程的状态保存下来,这样
              才能保证下次切换回来时,能基于上次切走的位置继续运行

  

2、什么是进程(理论)

进程:正在进行的一个过程或者说一个任务。nginx

进程即正在执行的一个过程。进程是对正在运行程序的一个抽象。web

狭义定义:进程是正在运行的程序的实例(an instance of a computer program that is being executed)。广义定义:进程是一个具备必定独立功能的程序关于某个数据集合的一次运行活动。它是操做系统动态执行的基本单元,在传统的操做系统中,进程既是基本的分配单元,也是基本的执行单元。算法

进程与程序的区别

​ 程序是指令和数据的有序集合,其自己没有任何运行的含义,是一个静态的概念。而进程是程序在处理机上的一次执行过程,它是一个动态的概念。程序能够做为一种软件资料长期存在,而进程是有必定生命期的。程序是永久的,进程是暂时的。shell

 

进程的并行与并发

不管是并行仍是并发,在用户看来都是'同时'运行的,无论是进程仍是线程,都只是一个任务而已,真是干活的是cpu,cpu来作这些任务,而一个cpu同一时刻只能执行一个任务windows

1、 并发:是伪并行,即看起来是同时运行。单个cpu+多道技术就能够实现并发,(并行也属于并发)。markdown

 

二 、并行:同时运行,只有具有多个cpu才能实现并行。并发

单核下,能够利用多道技术,多个核,每一个核也均可以利用多道技术(多道技术是针对单核而言的

有四个核,六个任务,这样同一时间有四个任务被执行,假设分别被分配给了cpu1,cpu2,cpu3,cpu4,

一旦任务1遇到I/O就被迫中断执行,此时任务5就拿到cpu1的时间片去执行,这就是单核下的多道技术

而一旦任务1的I/O结束了,操做系统会从新调用它(需知进程的调度、分配给哪一个cpu运行,由操做系统说了算),可能被分配给四个cpu中的任意一个去执行。

 

全部现代计算机常常会在同一时间作不少件事,一个用户的PC(不管是单cpu仍是多cpu),均可以同时运行多个任务(一个任务能够理解为一个进程)。

全部的这些进程都需被管理,因而一个支持多进程的多道程序系统是相当重要的。

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

 

进程的建立(了解)

凡是硬件,都须要有操做系统去管理,只要有操做系统,就有进程的概念,就须要有建立进程的方式,一些操做系统只为一个应用程序设计,好比微波炉中的控制器,一旦启动微波炉,进行通电,全部的进程都已经存在。

而对于通用系统(跑不少应用程序),须要有系统运行过程当中建立或撤销进程的能力,主要分为4中形式建立新的进程

  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)

 

进程的层次结构

不管UNIX仍是windows,进程只有一个父进程,不一样的是:

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

  2. 在windows中,没有进程层次的概念,全部的进程都是地位相同的,惟一相似于进程层次的暗示,是在建立进程时,父进程获得一个特别的令牌(称为句柄),该句柄能够用来控制子进程,可是父进程有权把该句柄传给其余子进程,这样就没有层次了。

 

 

进程的状态

在linux中执行

tail -f access.log |grep '404'

执行程序tail,开启一个子进程,执行程序grep,开启另一个子进程,两个进程之间基于管道'|'通信,将tail的结果做为grep的输入。

进程grep在等待输入(即I/O)时的状态称为阻塞,此时grep命令都没法运行

其实在两种状况下会致使一个进程在逻辑上不能运行,

  1. 进程挂起是自身缘由,遇到I/O阻塞,便要让出CPU让其余进程去执行,这样保证CPU一直在工做

  2. 与进程无关,是操做系统层面,可能会由于一个进程占用时间过多,或者优先级等缘由,而调用其余的进程去使用CPU。

于是一个进程由三种状态

 

 

进程并发的实现(了解)

进程并发的实如今于,硬件中断一个正在运行的进程,把此时进程运行的全部状态保存下来,为此,操做系统维护一张表格,即进程表(process table),每一个进程占用一个进程表项(这些表项也称为进程控制块)。

该表存放了进程状态的重要信息:程序计数器、堆栈指针、内存分配情况、全部打开文件的状态、账号和调度信息,以及其余在进程由运行态转为就绪态或阻塞态时,必须保存的信息,从而保证该进程在再次启动时,就像从未被中断过同样。

 

 

3、同步异步阻塞非阻塞

 在了解其余概念以前,咱们首先要了解进程的几个状态。在程序运行的过程当中,因为被操做系统的调度算法控制,程序会进入几个状态:就绪,运行和阻塞。

  (1)就绪(Ready)状态

  当进程已分配到除CPU之外的全部必要的资源,只要得到CPU即可当即执行,这时的进程状态称为就绪状态。

  (2)执行/运行(Running)状态当进程已得到CPU,其程序正在CPU上执行,此时的进程状态称为执行状态。

  (3)阻塞(Blocked)状态正在执行的进程,因为等待某个事件发生而没法执行时,便放弃CPU而处于阻塞状态。引发进程阻塞的事件可有多种,例如,等待I/O完成、申请缓冲区不能知足、等待信件(信号)等。

 

 

同步与异步  同步与异步是针对应用程序与内核的交互而言的。同步过程当中进程触发IO操做并等待或者轮询的去查看IO操做是否完成。异步过程当中进程触发IO操做之后,直接返回,作本身的事情,IO交给内核来处理,完成后内核通知进程IO完成。

阻塞与非阻塞  应用进程请求I/O操做时,若是数据未准备好,若是请求当即返回就是非阻塞,不当即返回就是阻塞。简单说就是作一件事若是不能当即得到返回,须要等待,就是阻塞,不然就能够理解为非阻塞。

 

例子

故事:老王烧开水。

出场人物:老张,水壶两把(普通水壶,简称水壶;会响的水壶,简称响水壶)。

老王想了想,有好几种等待方式

1.老王用水壶煮水,而且站在那里无论水开没开,每隔必定时间看看水开了没。-同步阻塞

老王想了想,这种方法不够聪明。

2.老王仍是用水壶煮水,再也不傻傻的站在那里看水开,跑去寝室上网可是仍是会每隔一段时间过来看看水开了没有,水没有开就走人。-同步非阻塞

老王想了想,如今的方法聪明了些,可是仍是不够好。

3.老王此次使用高大上的响水壶来煮水,站在那里可是不会再每隔一段时间去看水开,而是等水开了,水壶会自动的通知他。-异步阻塞

老王想了想,不会呀,既然水壶能够通知我,那我为何还要傻傻的站在那里等呢,嗯,得换个方法。

4.老王仍是使用响水壶煮水,跑到客厅上网去,等着响水壶本身把水煮熟了之后通知他。-异步非阻塞

老王豁然,这下感受轻松了不少。


  • 同步和异步

    同步就是烧开水,须要本身去轮询(每隔一段时间去看看水开了没),异步就是水开了,而后水壶会通知你水已经开了,你能够回来处理这些开水了。同步和异步是相对于操做结果来讲,会不会等待结果返回。

  • 阻塞和非阻塞

    阻塞就是说在煮水的过程当中,你不能够去干其余的事情,非阻塞就是在一样的状况下,能够同时去干其余的事情。阻塞和非阻塞是相对于线程是否被阻塞。

其实,这二者存在本质的区别,它们的修饰对象是不一样的。阻塞和非阻塞是指进程访问的数据若是还没有就绪,进程是否须要等待,简单说这至关于函数内部的实现区别,也就是未就绪时是直接返回仍是等待就绪。而同步和异步是指访问数据的机制,同步通常指主动请求并等待I/O操做完毕的方式,当数据就绪后在读写的时候必须阻塞,异步则指主动请求数据后即可以继续处理其它任务,随后等待I/O,操做完毕的通知,这可使进程在数据读写时也不阻塞。

小结

  1. 同步与异步针对的是函数/任务的调用方式:同步就是当一个进程发起一个函数(任务)调用的时候,一直等到函数(任务)完成,而进程继续处于激活状态。而异步状况下是当一个进程发起一个函数(任务)调用的时候,不会等函数返回,而是继续往下执行当,函数返回的时候经过状态、通知、事件等方式通知进程任务完成。

  2. 阻塞与非阻塞针对的是进程或线程:阻塞是当请求不能知足的时候就将进程挂起,而非阻塞则不会阻塞当前进程。

 

 

 

参考连接

[1]http://www.javashuo.com/article/p-gvgtjmbd-bc.html

相关文章
相关标签/搜索