协程(Coroutine)(一)
在使用easyswoole框架做开发的时候,经常需要使用到协程的并发查询。作为从传统fpm模式转到swoole内存常驻模式的PHPer,还是有一点吃力的。但是还是要迎刃而上,要想把协程用好,就先要把它弄清楚。学习过程中参考了《easyswoole官方文档》和《swoole官方文档》。
一、概念
协程不是进程或线程,一个程序可以包含多个协程,可以对比于一个进程包含多个线程。多个线程相对独立,有自己的上下文,切换受系统控制;而协程也相对独立,有自己的上下文,但是其切换由自己控制。
因此,协程可以说就是用户态的线程。内核态的线程是由操作系统来进行调度的,但是用户态的线程不是由操作系统来调度的,而是由程序员来调度的,是在用户态的。
二、协程调度
用户的每个请求都会创建一个协程,请求结束后协程结束,如果同时有成千上万的并发请求,某一时刻某个进程内部会存在成千上万的协程,那么 cpu 资源是有限的,到底执行哪个协程的代码?决定到底让 cpu 执行哪个协程的代码决断过程就是协程调度
1)首先,在执行某个协程代码的过程中发现这行代码遇到了 Co::sleep() 或者产生了网络 IO,例如 MysqL->query(),这肯定是一个耗时的过程,Swoole 就会把这个 MysqL 连接的 fd(事件的句柄)放到 EventLoop 中
2)然后让出这个协程的 cpu 给其他协程使用:即 yield(挂起),等待 MysqL 数据返回后就继续执行这个协程:即 resume(恢复)
3)其次,如果协程的代码中有cpu密集型代码,我们可以开启enable_preemptive_scheduler,Swoole 会强行让这个协程让出 cpu。
三、协程的实现
1)yield生成器实现 (详细原理可查看http://www.PHP20.cn/article/148)
2)swoole扩展实现
说明:同时由于底层封装了协程,所以对比传统的 PHP 层协程框架,开发者不需要使用 yield 关键词来标识一个协程 IO 操作,所以不再需要对 yield 的语义进行深入理解以及对每一级的调用都修改为 yield,这极大的提高了开发效率
四、协程的生命周期
协程内的生命周期与普通PHP函数一致,当协程退出后,协程内变量将全部回收.
五、注意事项
1、协程环境
使用协程容器,才可以创建协程,否则没有协程环境,不能实现协程切换功能.不能用\co::sleep
2、变量使用
1)在协程中,需要特别注意,不要使用$_GET,$_POST,$GLOBALS等超全局变量,尤其是需要修改变量值并读取时,将造成协程间变量污染.
2)协程中访问外部变量必须使用use关键字,或者传形参方式,不能引用变量.
3)如果需要做多协程之间的通信,可使用channel方式通信.
3、缩写
Go()是\Co::create() 的缩写, 用来创建一个协程, 接受 callback 作为参数, callback 中的代码, 会在这个新建的协程中执行.
备注: \Swoole\Coroutine 可以简写为 \Co
参考链接:
https://www.easyswoole.com
https://wiki.swoole.com/#/start/coroutine
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。