详解php协程知识点


Posted in PHP onSeptember 21, 2018

多任务 (并行和并发)

在讲协程之前,先谈谈多进程、多线程、并行和并发。

对于单核处理器,多进程实现多任务的原理是让操作系统给一个任务每次分配一定的 CPU 时间片,然后中断、让下一个任务执行一定的时间片接着再中断并继续执行下一个,如此反复。

由于切换执行任务的速度非常快,给外部用户的感受就是多个任务的执行是同时进行的。

多进程的调度是由操作系统来实现的,进程自身不能控制自己何时被调度,也就是说: 进程的调度是由外层调度器抢占式实现的

而协程要求当前正在运行的任务自动把控制权回传给调度器,这样就可以继续运行其他任务。这与抢占式的多任务正好相反, 抢占多任务的调度器可以强制中断正在运行的任务, 不管它自己有没有意愿。如果仅依靠程序自动交出控制的话,那么一些恶意程序将会很容易占用全部 CPU 时间而不与其他任务共享。

协程的调度是由协程自身主动让出控制权到外层调度器实现的

回到刚才生成器实现 xrange 函数的例子,整个执行过程的交替可以用下图来表示:

协程可以理解为纯用户态的线程,通过协作而不是抢占来进行任务切换。

相对于进程或者线程,协程所有的操作都可以在用户态而非操作系统内核态完成,创建和切换的消耗非常低。

简单的说协程 就是提供一种方法来中断当前任务的执行,保存当前的局部变量,下次再过来又可以恢复当前局部变量继续执行。

我们可以把大任务拆分成多个小任务轮流执行,如果有某个小任务在等待系统 IO,就跳过它,执行下一个小任务,这样往复调度,实现了 IO 操作和 CPU 计算的并行执行,总体上就提升了任务的执行效率,这也便是协程的意义

多线程

在单核下,多线程必定是并发的;

不过现在的统一进程的多线程是可以运行在多核CPU下,所以可以是并行的

并发(Concurrency)

是指能处理多个同时性活动的能力,并发事件之间不一定要同一时刻发生。

并行(Parallesim)

是指同时发生的两个并发事件,具有并发的含义,而并发则不一定并行。
多个操作可以在重叠的时间段内进行。

并行和并发区别

并发指的是程序的结构,并行指的是程序运行时的状态

并行一定是并发的,并行是并发设计的一种

单线程永远无法达到并行状态

协程

协程的支持是在生成器的基础上, 增加了可以回送数据给生成器的功能(调用者发送数据给被调用的生成器函数).

这就把生成器到调用者的单向通信转变为两者之间的双向通信.

我们在上篇文章已经讲过了send方法, 下面让我们理解下协程

同步代码

在没有涉及到异步执行代码之前,我们的代码都是这样的

function printNum($max, $caller)
{
  for ($i=0; $i<$max; $i++ ) {
    echo "调度者:" . $caller . " 打印:" . $i . PHP_EOL;
  }
}
 
printNum(3, "caller1");
printNum(3, "caller2");
 
# output
调度者:caller1 打印:0
调度者:caller1 打印:1
调度者:caller1 打印:2
调度者:caller2 打印:0
调度者:caller2 打印:1
调度者:caller2 打印:2

使用协程后改进的代码

初稿,手动调整生成器执行

# 本代码手动调整了进程执行代码的顺序,当然本代码实现不用协程也可以,只是利用本流程说明协程作用
# 生成器给了我们函数中断,协程[生成器send]给了我们重新唤起生成器函数的能力
function printNumWithGen($max)
{
  for ($i=0; $i<$max; $i++ ) {
    $res = yield $i;
    echo $res;
  }
}
 
$gen1 = printNumWithGen(3);
$gen2 = printNumWithGen(3);
 
// 手动执行caller1 再 caller2
$gen1->send("调度者: caller1 打印:" . $gen1->current() . PHP_EOL);
$gen2->send("调度者: caller2 打印:" . $gen2->current() . PHP_EOL);
 
// 手动执行caller1 再 caller2
$gen1->send("调度者: caller1 打印:" . $gen1->current() . PHP_EOL);
$gen2->send("调度者: caller2 打印:" . $gen2->current() . PHP_EOL);
 
// 手动执行caller2 再 caller1
$gen2->send("调度者: caller2 打印:" . $gen2->current() . PHP_EOL);
$gen1->send("调度者: caller1 打印:" . $gen1->current() . PHP_EOL);
 
# output
调度者: caller1 打印:0
调度者: caller2 打印:0
调度者: caller1 打印:1
调度者: caller2 打印:1
调度者: caller2 打印:2
调度者: caller1 打印:2

总结

上面案例应该让大家理解了协程设计的意义和如何使用协程

那么接下去我们为我们的协程自动一个自动调度器(Co自动执行器),无需再手动来中断和恢复了

PHP 相关文章推荐
php数组函数序列之in_array() - 查找数组中是否存在指定值
Nov 07 PHP
基于在生产环境中使用php性能测试工具xhprof的详解
Jun 03 PHP
php生成zip压缩文件的方法详解
Jun 09 PHP
PHP实现恶意DDOS攻击避免带宽占用问题方法
May 27 PHP
浅析PHP7新功能及语法变化总结
Jun 17 PHP
PHP数组中头部和尾部添加元素的方法(array_unshift,array_push)
Apr 10 PHP
php原生数据库分页的代码实例
Feb 18 PHP
PHP 7.4 新语法之箭头函数实例详解
May 09 PHP
Laravel5.4简单实现app接口Api Token认证方法
Aug 29 PHP
浅谈laravel 5.6 安装 windows上使用composer的安装过程
Oct 18 PHP
PHP单元测试配置与使用方法详解
Dec 27 PHP
PHP底层运行机制与工作原理详解
Jul 31 PHP
在php的yii2框架中整合hbase库的方法
Sep 20 #PHP
php实现在线考试系统【附源码】
Sep 18 #PHP
PHP htmlspecialchars() 函数实例代码及用法大全
Sep 18 #PHP
Laravel用户授权系统的使用方法示例
Sep 16 #PHP
Laravel中错误与异常处理的用法示例
Sep 16 #PHP
laravel获取不到session的三种解决办法【推荐】
Sep 16 #PHP
win7 wamp 64位 php环境开启curl服务遇到的问题及解决方法
Sep 16 #PHP
You might like
php在字符串中查找另一个字符串
2008/11/19 PHP
PHP安全技术之 实现php基本安全
2010/09/04 PHP
10条PHP高级技巧[修正版]
2011/08/02 PHP
php实现json编码的方法
2015/07/30 PHP
[原创]CI(CodeIgniter)简单统计访问人数实现方法
2016/01/19 PHP
CI框架附属类用法分析
2018/12/26 PHP
php设计模式之策略模式实例分析【星际争霸游戏案例】
2020/03/26 PHP
KindEditor在php环境下上传图片功能集成的方法示例
2020/07/20 PHP
js+FSO遍历文件夹下文件并显示
2007/03/07 Javascript
JS截取url中问号后面参数的值信息
2014/04/29 Javascript
javascript学习笔记(四)function函数部分
2014/09/30 Javascript
JavaScript实现级联菜单的方法
2015/06/29 Javascript
使用getBoundingClientRect方法实现简洁的sticky组件的方法
2016/03/22 Javascript
详解在Vue中如何使用axios跨域访问数据
2017/07/07 Javascript
Webpack中publicPath路径问题详解
2018/05/03 Javascript
从零搭一个自用的前端脚手架的方法步骤
2019/09/23 Javascript
python实现计算倒数的方法
2015/07/11 Python
Python数据库的连接实现方法与注意事项
2016/02/27 Python
Python装饰器用法实例总结
2018/02/07 Python
Python中pandas模块DataFrame创建方法示例
2018/06/20 Python
Django自带的加密算法及加密模块详解
2019/12/03 Python
Python3自动生成MySQL数据字典的markdown文本的实现
2020/05/07 Python
python requests库的使用
2021/01/06 Python
驴妈妈旅游网:中国新型的B2C旅游电子商务网站
2016/08/16 全球购物
Doyoueven官网:澳大利亚健身服饰和配饰品牌
2019/03/24 全球购物
世界顶级户外运动品牌折扣网站:LeftLane Sports
2019/06/12 全球购物
美国第一大药店连锁机构:Walgreens(沃尔格林)
2019/10/10 全球购物
中国电子产品批发商/跨境电商/外贸网:Sunsky-online
2020/04/20 全球购物
材料化学应届生求职信
2013/10/09 职场文书
汽车运用工程专业毕业生推荐信
2013/12/25 职场文书
办公室主任岗位承诺书
2014/05/29 职场文书
布达拉宫的导游词
2015/02/02 职场文书
邀请函样本
2015/02/02 职场文书
vue3中provide && inject的使用
2021/07/01 Vue.js
Win10 heic文件怎么打开 ? Win10 heic文件打开教程
2022/04/06 数码科技
教你如何用cmd快速登录服务器
2022/06/10 Servers