协程执行顺序
//hyperf框架
use Co;go(function () {Co::sleep(1); // Io等待一秒echo "hello go1 \n";});echo "hello main \n";go(function () {echo "hello go2 \n";});//打印结果hello mainhello go2hello go1/*运行此段代码, 系统启动一个新进程程序从上往下执行遇到第一个 go(), 当前进程中生成一个协程协程中遇到 IO阻塞 (这里是 Co::sleep() 模拟出的 IO等待), 协程让出控制, 进入协程调度队列进程继续向下执行, 输出 hello main,不会等待上面的go程执行完。所以是异步的。执行下一个协程, 输出 hello go2之前的协程准备就绪, 继续执行, 输出 hello go1/*
- 协程没有 IO 等待的时候,正常执行 PHP 代码,不会产生执行流程切换
- 单个协程内的代码运行仍是串行的,从上往下执行
- 协程遇到 IO 等待 立即将控制权切换,待 IO 完成后,重新将执行流切回原来协程切出的点
- 多个协程的执行顺序是无法确定的,由调度器自行决定。Go的调度器使用并发和并行的方式来执行协程,具体的调度策略是非确定性的
- 协程嵌套执行流程由外向内逐层进入,直到发生 IO,然后切到外层协程,父协程不会等待子协程结束,即为主死从亡
注意要点
协程中不能存在阻塞代码
- 有阻塞代码
白开协程了
go(function () {sleep(1); // 未开启协程 runtime, 此处会阻塞, 输出为 go -> mainecho "go \n";
});
echo "main \n";
执行结果为
go
main
sleep()是原生php语句,阻塞式的
- 无阻塞代码
Co::sleep()触发协程调度器
//一键开启协程
\Swoole\Runtime::enableCoroutine();go(function () {sleep(1); // 开启协程 runtime, 此处为阻塞, 输出为 main -> go//不开启一键协程,也可以使用 Co::sleep(1)来实现;echo "go \n";
});
echo "main \n";
执行结果
main
go