千家信息网

PHP协程与阻塞举例分析

发表于:2024-11-22 作者:千家信息网编辑
千家信息网最后更新 2024年11月22日,本篇内容介绍了"PHP协程与阻塞举例分析"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!进程、线程、协
千家信息网最后更新 2024年11月22日PHP协程与阻塞举例分析

本篇内容介绍了"PHP协程与阻塞举例分析"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

进程、线程、协程

关于进程、线程、协程,有非常详细和丰富的博客或者学习资源,我不在此做赘述,我大致在此介绍一下这几个东西。

  1. 进程拥有自己独立的堆和栈,既不共享堆,亦不共享栈,进程由操作系统调度。

  2. 线程拥有自己独立的栈和共享的堆,共享堆,不共享栈,线程亦由操作系统调度(标准线程是的)。

  3. 协程和线程一样共享堆,不共享栈,协程由程序员在协程的代码里显示调度。

PHP中的协程实现基础 yield

yield的根本实现是生成器类,而迭代器类是迭代器接口的实现:

Generator implements Iterator {     public mixed current ( void ) // 返回当前产生的值     public mixed key ( void ) // 返回当前产生的键     public void next ( void ) // 生成器继续执行     public void rewind ( void ) // 重置迭代器,如果迭代已经开始了,这里会抛出一个异常。                                              // renwind的执行将会导致***个yield被执行, 并且忽略了他的返回值.     public mixed send ( mixed $value ) // 向生成器中传入一个值,并且当做 yield 表达式的结果,然后继续执行生成器。如果当这个方法被调用时,生成器                                                // 不在 yield 表达式,那么在传入值之前,它会先运行到***个 yield 表达式。     public void throw ( Exception $exception ) // 向生成器中抛入一个异常     public bool valid ( void ) // 检查迭代器是否被关闭     public void __wakeup ( void ) // 序列化回调,抛出一个异常以表示生成器不能被序列化。 }

自定义简单定时执行任务示例:

(此例子必须依赖于以上鸟哥实现的协程调度代码)

class timer {     private $start = 0; // 定时开始时间     private $timer; // 间隔的时间差,单位秒     private $value = 0; // 产生的结果值     private $callback; // 异步回调     private $isEnd = false; // 当前定时器任务是否结束     public function __construct($timer,callable $callback)     {         $this->start = time();         $this->timer = $timer;         $this->callback = $callback;     }     public function run() {         if($this->valid()) {             $callback = $this->callback;             $callback($this->value ++,$this);             $this->start = time();         }     }     /**      * 定时执行检查      */     public function valid() {         $end = time();         if($end - $this->start >= $this->timer) {             return true;         } else {             return false;         }     }     public function setEnd($isEnd) {         $this->isEnd = $isEnd;     }     public function getEnd() {         return $this->isEnd;     } }  /**  * 模拟阻塞的协程1  *  */ function taskObject1() {     $timer = new timer(1,function($value,timer $timer) {         if($value >= 5) {             $timer->setEnd(true);         }         echo '
'.'A '.$value; }); $tid = (yield getTaskId()); while (true) { if($timer->getEnd() == true) { break; } yield $timer->run(); } } /** * 模拟阻塞的协程2 * */ function taskObject2() { $timer = new timer(2,function($value,timer $timer) { if($value >= 3) { $timer->setEnd(true); } echo '
'.'B '.$value; }); $tid = (yield getTaskId()); while (true) { if($timer->getEnd() == true) { break; } yield $timer->run(); } } $scheduler = new Scheduler; $scheduler->newTask(taskObject1()); $scheduler->newTask(taskObject2()); $scheduler->run();

以上实现的是:

  1. 产生两个任务,并行执行,并且给每个任务在执行的时候模拟几秒钟的阻塞;

  2. 让协程切换的时候能顺利切换,其中的任务阻塞不相互影响;

思考:

我为什么要做以上这件事情呢?因为我发现协程实现虽然很强大也很有意思,能让多任务并行,但是我在其中一个任务里调用系统函数 sleep() 的时候,阻塞任务会阻止协程切换,其实从协程的实现原理上来书也是这么回事。

那么,我也就想模拟协程阻塞,但是不产生阻塞看是否可行。PHP本身只提供了生成器为协程调用提供了支撑,如果不依赖扩展,没有提供多线程的程序实现方式,没有java那么强大,可以开子线程进行实现。

我印象中java的子线程是独立执行且不会相互阻塞的,所以我在想,PHP既然可以实现类似于多线程这样的机制,那么能不能实现调用过程中非阻塞呢?

经过这样一个实现和思考,一开始是陷入了一个误区的,是由于PHP原生函数 sleep() 阻塞造成的思维误区,那就是认为要想真正实现非阻塞或者说实现异步的话,是必须依赖于语言底层的。

后来,我想明白了一个道理,既然某个方法或者函数在执行过程中,会产生阻塞,那么把当前这个方法换成自定义的,做成非阻塞(相对于整个协程调度来说)不就行了吗?比如上面的定时执行我自己实现了一个。

而另一方面,协程调度本身的目的也是为了把任务执行过程切成尽量小片,从而快速切换执行,达到并行的目的。从这方面来看,协程应该也算是一种程序设计思想。

以下是一个程序切成尽量小片执行的例子:

// 一个简单的例子 

这个例子是把原本用 range 生成一个很大的整型数组的方式切换为分片执行,也就是说在遍历的时候再去取到指定的值,从代码上来看,内存消耗相对于之前来说就非常小了。

"PHP协程与阻塞举例分析"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注网站,小编将为大家输出更多高质量的实用文章!

阻塞 线程 任务 生成 生成器 调度 切换 迭代 例子 时候 程序 过程 进程 代码 函数 方法 系统 表达式 独立 分析 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 软件开发公司的免责协议 成都工控软件开发价格表 阿里云服务器4核4g 综合技能应用网络技术 怎么把服务器系统全部磁盘备份 下载商丘市网络安全课堂 idea对数据库进行访问 常见项目管理服务器有哪些 问道手游怎么连接服务器 游戏服务器自动寻路管理视野 优化的优劣直接影响数据库的性能 河南智游网络技术 网络安全风险处置报告 ff17大厅服务器 技术网络技术服务包括什么 网络技术最好的院系 网络安全什么保护 宝山区多功能软件开发厂家直销 纯视觉自动驾驶数据库比对 货车司机数据库 单位如何做好网络安全 衢州龙游县专业软件开发地址 网页数据存在服务器哪里 手机版软件开发教程 线上网络安全宣传周 表格怎样更新多行的数据库中 上海运维服务软件开发哪家好 怀旧服服务器自动断开 第一个油菜基因转录数据库 杭州足浴软件开发系统
0