在IO编程一节中,我们已经知道,CPU的速度远远快于磁盘、网络等IO。在一个线程中,CPU执行代码的速度极快,然而,一旦遇到IO操作,如读写文件、发送网络数据时,就需要等待IO操作完成,才能继续进行下一步操作。这种情况称为同步IO。

在IO操作的过程中,当前线程被挂起,而其他需要CPU执行的代码就无法被当前线程执行了。

因为一个IO操作就阻塞了当前线程,导致其他代码无法执行,所以我们必须使用多线程或者多进程来并发执行代码,为多个用户服务。每个用户都会分配一个线程,如果遇到IO导致线程被挂起,其他用户的线程不受影响。

多线程和多进程的模型虽然解决了并发问题,但是系统不能无上限地增加线程。由于系统切换线程的开销也很大,所以,一旦线程数量过多,CPU的时间就花在线程切换上了,真正运行代码的时间就少了,结果导致性能严重下降。

由于我们要解决的问题是CPU高速执行能力和IO设备的龟速严重不匹配,多线程和多进程只是解决这一问题的一种方法。

另一种解决IO问题的方法是异步IO。当代码需要执行一个耗时的IO操作时,它只发出IO指令,并不等待IO结果,然后就去执行其他代码了。一段时间后,当IO返回结果时,再通知CPU进行处理。

可以想象如果按普通顺序写出的代码实际上是没法完成异步IO的:

do_some_code()
f = open('/path/to/file', 'r')
r = f.read() # <== 线程停在此处等待IO操作结果
# IO操作完成后线程才能继续执行:
do_some_code(r)

所以,同步IO模型的代码是无法实现异步IO模型的。

异步IO模型需要一个消息循环,在消息循环中,主线程不断地重复“读取消息-处理消息”这一过程:

loop = get_event_loop()
while True:
event = loop.get_event()
process_event(event)

消息模型其实早在应用在桌面应用程序中了。一个GUI程序的主线程就负责不停地读取消息并处理消息。所有的键盘、鼠标等消息都被发送到GUI程序的消息队列中,然后由GUI程序的主线程处理。

由于GUI线程处理键盘、鼠标等消息的速度非常快,所以用户感觉不到延迟。某些时候,GUI线程在一个消息处理的过程中遇到问题导致一次消息处理时间过长,此时,用户会感觉到整个GUI程序停止响应了,敲键盘、点鼠标都没有反应。这种情况说明在消息模型中,处理一个消息必须非常迅速,否则,主线程将无法及时处理消息队列中的其他消息,导致程序看上去停止响应。

消息模型是如何解决同步IO必须等待IO操作这一问题的呢?当遇到IO操作时,代码只负责发出IO请求,不等待IO结果,然后直接结束本轮消息处理,进入下一轮消息处理过程。当IO操作完成后,将收到一条“IO完成”的消息,处理该消息时就可以直接获取IO操作结果。

在“发出IO请求”到收到“IO完成”的这段时间里,同步IO模型下,主线程只能挂起,但异步IO模型下,主线程并没有休息,而是在消息循环中继续处理其他消息。这样,在异步IO模型下,一个线程就可以同时处理多个IO请求,并且没有切换线程的操作。对于大多数IO密集型的应用程序,使用异步IO将大大提升系统的多任务处理能力。

六十三 、异步IO的更多相关文章

  1. Mina源码阅读笔记(六)—Mina异步IO的实现IoFuture

    IoFuture是和IoSession紧密相连的一个类,在官网上并没有对它的描述,因为它一般不会显示的拿出来用,权当是一个工具类被session所使用.当然在作用上,这个系列可并不简单,我们先看源码的 ...

  2. Mina、Netty、Twisted一起学(九):异步IO和回调函数

    用过JavaScript或者jQuery的同学都知道,JavaScript特别是jQuery中存在大量的回调函数,例如Ajax.jQuery的动画等. $.get(url, function() { ...

  3. C#编程总结(六)异步编程

    C#编程总结(六)异步编程 1.什么是异步? 异步操作通常用于执行完成时间可能较长的任务,如打开大文件.连接远程计算机或查询数据库.异步操作在主应用程序线程以外的线程中执行.应用程序调用方法异步执行某 ...

  4. python 全栈开发,Day44(IO模型介绍,阻塞IO,非阻塞IO,多路复用IO,异步IO,IO模型比较分析,selectors模块,垃圾回收机制)

    昨日内容回顾 协程实际上是一个线程,执行了多个任务,遇到IO就切换 切换,可以使用yield,greenlet 遇到IO gevent: 检测到IO,能够使用greenlet实现自动切换,规避了IO阻 ...

  5. {python之IO多路复用} IO模型介绍 阻塞IO(blocking IO) 非阻塞IO(non-blocking IO) 多路复用IO(IO multiplexing) 异步IO(Asynchronous I/O) IO模型比较分析 selectors模块

    python之IO多路复用 阅读目录 一 IO模型介绍 二 阻塞IO(blocking IO) 三 非阻塞IO(non-blocking IO) 四 多路复用IO(IO multiplexing) 五 ...

  6. JAVA I/O(六)多路复用IO

    在前边介绍Socket和ServerSocket连接交互的过程中,读写都是阻塞的.套接字写数据时,数据先写入操作系统的缓存中,形成TCP或UDP的负载,作为套接字传输到目标端,当缓存大小不足时,线程会 ...

  7. python---爬虫相关性能(各个异步模块的使用,和自定义异步IO模块)

    一:线程池,进程池等相关文章了解 python---基础知识回顾(十)进程和线程(py2中自定义线程池和py3中的线程池使用) python---基础知识回顾(十)进程和线程(协程gevent:线程在 ...

  8. python笔记-10(socket提升、paramiko、线程、进程、协程、同步IO、异步IO)

    一.socket提升 1.熟悉socket.socket()中的省略部分 socket.socket(AF.INET,socket.SOCK_STREAM) 2.send与recv发送大文件时对于黏包 ...

  9. 爬虫之多线程 多进程 自定义异步IO框架

    什么是进程? 进程是程序运行的实例,是系统进行资源分配和调度的一个独立单位,它包括独立的地址空间,资源以及1个或多个线程. 什么是线程? 线程可以看成是轻量级的进程,是CPU调度和分派的基本单位. 进 ...

随机推荐

  1. Google新出品的数据格式:Protocol Buffer

    转:http://blog.csdn.net/carson_ho/article/details/70037693

  2. eclipse的最新版本luna的中建立svn和maven

    http://blog.csdn.net/notillusion/article/details/40950185

  3. LruCache:从网络加载图片缓存实例

    OOM异常 堆内存用于存储实例对象,当程序不断创建对象,并且对象都有引用指向,那么垃圾回收机制就不会清理这些对象,当对象多到挤满堆内存的上限后,就产生OOM异常.Android系统为每个应用程序使用的 ...

  4. 深度学习---tensorflow简介

    个core可以有不同的代码路径.对于反向传播算法来说,基本计算就是矩阵向量乘法,对一个向量应用激活函数这样的向量化指令,而不像在传统的代码里会有很多if-else这样的逻辑判断,所以使用GPU加速非常 ...

  5. linux查看文件相关指令

    以下内容整理自以下两篇文章: http://www.cnblogs.com/xilifeng/archive/2012/10/13/2722596.html Linux 查看文件内容的命令 http: ...

  6. Create MSSQL Procedure

    代码: CREATE PROCEDURE [dbo].[sp_UpdateCouponCount] AS GO

  7. 【转载】Quick-Cocos2d-x文件结构分析

    在上一章我们讲过了Quick-Cocos2d-x中的环境搭建,这章我们分析下quick中的文件结构吧!打开quick的文件夹,可以看到如下的这些目录和文件: bin:存放各种与引擎相关的脚本 comp ...

  8. Vuejs - 单文件组件

    为什么需要单文件组件 在之前的实例中,我们都是通过 Vue.component 或者 components 属性的方式来定义组件,这种方式在很多中小规模的项目中还好,但在复杂的项目中,下面这些缺点就非 ...

  9. 微信小程序滑动选择器

    实现微信小程序滑动选择效果 在wxml文件中,用一个picker标签代表选择器,bindchange是用户点击确定后触发的函数,index是picker自带的参数,用户点击确定后,bindchange ...

  10. bzoj 2440 dfs序

    首先我们可以做一遍dfs,用一个队列记录每个点进出的顺序,当每个点访问的时候que[tot++]=x,记为in[x],当结束dfs的时候que[tot++]=x,记为out[x],这样处理出来的队列, ...