1. 异步编程[1] 同步和异步描述的是进程/线程的调用方式
同步和异步 - 同步调用指的是线程发起调用后,一直等待调用返回后才继续执行下一步操作,这并不代表
CPU 在这段时间内也会一直等待,操作系统多半会切换到另一个线程上去,等到调用返回后再切换回原来的线程。 - 异步就相反,发起调用后,线程继续向下执行,当调用返回后,通过某种手段来通知调用者。
解释和说明 我们需要注意同步和异步过程中的调用返回,指的是内核进程将数据复制到调用进程。上面说的顺序式编程里面,通常调用就是同步的,上一步执行结束之后才会执行下一步。而异步编程中,如果遇到等待的操作,会继续往下执行,直到请求返回结果在进行处理。 写一个使用多线程或多进程抓取网站内容的爬虫,但由于网络请求或对方网站等问题,导致某段时间内的请求网站请求很慢。即使设置的超时时间,那么在超时时间到来之前,这些进程或线程都是一个等待的状态,什么也干不了。 而异步编程就很适合使用在如上的场景中,它可以通过切换任务的方式尽量减少闲置时间。如遇到等待的请求就先回跳过并执行下一个请求,等执行完成之后再回到这个请求。如果还是没有就绪,就切换到下下一个请求。
[2] 同步和异步编程模型解释及其图示说明
单线程的同步模型 多线程/多进程的同步模型 异步编程模型 这个任务是在单线程的控制下任务交错完成的,相对于多线程或多进程简单很多,没有了内容复制、资源传递的问题。而且,程序的控制权完全在我们手里,而不会被操作系统收回自行处理。 在这种异步编程模型,开发者只需要将任务组织成为一个序列,交替的小步完成。每一个异步调用需要足够的小,当然不能耗时太久。 可以看到下一图中的这种模型,并没有看到异步编程的太多的优势的,而且线程之间的切换还会带来额外的开销。异步编程,适应于那些任务强制等待或者阻塞的时候,才能发挥其优势所在。
[3] 操作系统模型中的进程变化状态
阻塞和非阻塞
2. IO 编程模型该编程模型是为了解决 I/O 比较慢而产生的,熟悉和理解该模型有利于我们自己编写异步非阻塞的代码
什么是 IO 模型 当I/O发生的时候就会涉及到对象和步骤的操作,我们这里以网络I/O的read为例。它会涉及到两个系统对象,一个是调用这个I/O操作的进程或线程,另一个就是系统内核。当read操作发生时,第一步会等待数据准备(磁盘到内核内存),第二步会将数据从内核拷贝到进程中去(内核内存到进程内存)。 而在Python编程中,第一阶段是准备数据阶段,第二阶段是返回计算结果阶段。所以对于下面的模型说明,需要我们自行对照理解。
[1] 阻塞型 I/O 模型
[2] 非阻塞 I/O 模型 [3] 复用 I/O 模型 [4] 信号驱动式 IO 模型 [5] 异步 IO 模型 五种I/O模型里面,除了异步IO模型以外,都是同步的。所以,再次验证了阻塞并不等于同步,非阻塞并不等于异步。 异步I/O模型,应用进程只需要通知内核,内核默默的完成第一和第二阶段,完成之后通知进程已经完成了。真正的实现了不阻塞、不等待的模型。一个进程可以响应多个请求,性能极大地提升。 水平触发:完成之后通知应用进程,如果没有收到,会一直发送,直到处理位置,非常消耗资源。 边缘触发:完成之后通知应用进程,只通知一次,如果没有处理则存放起来并告诉其位置,比较好的方式。
3. 事件驱动这些使用场景大多出现在C/S 模型中网络比较繁忙的服务器端
异步模型的使用场景 事件驱动模型就是通过事件来触发对应的操作
事件驱动模型 事件驱动模型主要应用在图形用户界面、网络服务和Web前端上。举个编写图形用户界面程序的例子,要给界面上每一个按钮都添加监听函数,而该函数则只有在相应的按钮被用户点击的事件发生时才会执行,开发者并不需要事先确定事件何时发生,只需要编写事件的响应函数即可。监听函数或者响应函数就是所谓的事件处理器(event handler),类似的事件还有鼠标移动、按下、松开、双击等等,这就是事件驱动。 事件驱动的程序一般都有一个主循环(main loop)或称事件循环(event loop),该循环不停地做两件事:事件监测和事件处理。首先要监测是否发生了事件,如果有事件发生则调用相应的事件处理程序,处理完毕再继续监测新事件。事件循环只是在一个进程中运行的单个线程 在Python2标志性的异步框架就是Tornado(也存在事件循环)、Twisted(基于事件驱动的网络引擎框架)、Gevent(使用的是协程),它们的共同特点就是异步非阻塞,而在Python3.6标准库中已经自带了asyncio。
原文链接:https://www.escapelife.site/posts/ab1905ae.html
文章转载:Python编程学习圈 (版权归原作者所有,侵删)
|