阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

异步IO

26次阅读
没有评论

共计 1324 个字符,预计需要花费 4 分钟才能阅读完成。

在 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 将大大提升系统的多任务处理能力。

正文完
星哥说事-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2024-08-07发表,共计1324字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中