python - tornado关于协程疑问
天蓬老师
天蓬老师 2017-04-18 09:35:06
[Python讨论组]
天蓬老师
天蓬老师

欢迎选择我的课程,让我们一起见证您的进步~~

全部回复(2)
PHP中文网

同步和异步

异步的概念相对于同步,主要指程序执行的时候,普通函数调用与系统调用执行的运行状态。

在网络IO,通常需要系统调用accept获取连接和read获取数据。并且由于IO比较耗时,所以这两个系统调用到返回用户代码就存在阻塞和非阻塞。下面以read调用为例:

# 读取网络数据系统调用
data = read()   

# 执行任务A
A.task()

对于同步模型,read函数调用之后,用户代码就无法往下执行A,用户进程就休眠了。操作系统进程则在进行缓存区数据的等待和读取,直到系统的read函数调用返回数据之后,用户进程才从休眠中醒来。然后执行A.task

对于异步模型,read函数调用之后,会向系统注册一个回调函数,用户进程并没有休眠,而是继续往下执行A.task,与此同时,操作系统的进程与同步模型时候的一样,也在等待数据和读取。只不过此时,操作系统的readA.task他们之间并没有先后顺序,而是各种执行各自的逻辑。看起来就是不同(异)的函数在执行(步)。当操作系统read执行完毕就会回调通知用户进程,并把数据返回。

异步和协程

异步和协程不能完全等同,他们的相似点都是函数执行的一种方式。协程,顾名思义就是协商程序(函数)。通常函数执行之后,要么返回,要么阻塞,阻塞一定条件之后返回。协程的函数则是函数执行到某个逻辑,设置一执行点,然后返回控制权,一旦某些条件满足了,再从刚设置的执行点进行接下来的函数逻辑,最后才返回。python中通常使用yield实现。这种执行流和异步很像。例如:


def get():
    # 读取网络数据系统调用
    data = yield read()   

    # 执行任务A
    A.task(data)

def post():
    pass

协程和异步的实现效果类似,调用read后不会阻塞,而是返回控制权。对于get中,还是不能执行A.task,直到read数据到达,然后再从yield执行,最后执行A。这个流程与同步的差别在于,如果是同步,不仅是A无法执行,别的地方的代码也无法执行,比如 post中的逻辑。而协程的调用时候,get中的A.task无法执行,可是post中的其他代码是可以执行的。同步和异步对比中,看问题的观察点是get函数内,协程的观察点是get和post函数。

tornado的io

tornado的IO指的是处理网络连接的异步,即epoll(kqueue)方式处理连接。如果tornado的handler的单个请求中查询数据库,这里的IO就类似 get的read操作。既可以是同步,也可以是异步。只不过,如果这里使用了阻塞IO,那么整个tornado进程处理网络IO的时候,也会阻塞。

伊谢尔伦

使用协程的场景主要就是处理io。异步和协程不是同一类概念,不能说最大的区别是什么。协程是加强版生成器,只是实现异步的一种方案。也可以用线程,进城实现异步io,基本上跑不了epoll等函数。只要是io操作,基本都有延时,不管是网络还是本地文件读写,所以都适用异步io。

如果需要看参考书,推荐unix网络编程,只用看相关概念即可,比如几种常见的io模型,阻塞与非阻塞,同步和异步的概念。

热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习
PHP中文网抖音号
发现有趣的

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号