百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术资源 > 正文

「服务器」协程探秘,你知多少 协程使用

lipiwang 2024-11-01 14:09 6 浏览 0 评论

协程不是进程或线程,其执行过程更类似于子例程,或者说不带返回值的函数调用。在所有语言中子程序都是层级调用,比如A调用B,B在执行过程中又调用了C,C执行完毕返回,B执行完毕返回,最后是A执行完毕。所以子程序调用是通过栈实现的,一个线程就是执行一个子程序。

子程序调用总是一个入口,一次返回,调用顺序是明确的,而协程的调用和子程序不同。协程看上去也是子程序,但执行过程中,在子程序内部可中断,然后转而执行别的子程序,在适当的时候再返回来接着执行,而协程却可以进入多次并返回多次。

上图中的程序,如果是一个子程序,那么它只能把 1、2、3 依次执行后,才返回。如果是协程,它可能在 1 处暂停,然后在某个时刻从 2 处继续执行;接着在 2 处执行完之后暂停,然后在另外一个时刻从 3 处继续执行。

协程虽然是一个线程执行,但和多线程相比,其最大的优势就是极高的执行效率。子程序切换不是线程切换,而是由程序自身控制,因此,没有线程切换的开销,和多线程比,线程数量越多,协程的性能优势就越明显。

另外,协程不需要多线程的锁机制,因为只有一个线程,也不存在同时写变量冲突,在协程中控制共享资源不加锁,只需要判断状态就好了,所以执行效率比多线程高很多。

使用PHP实现协程

从PHP5.5开始,php开始了对迭代(生成)器和协程的支持。对协程的支持是在迭代生成器的基础上,增加了可以回送数据给生成器的功能(调用者发送数据给被调用的生成器函数),这就把生成器到调用者的单向通信转变为两者之间的双向通信。如:

示例代码

那么什么是迭代(生成)器呢?

迭代(生成)器也是一个函数,不同的是这个函数的返回值是依次返回,而不是只返回一个单独的值。

下面通过实现一个xrange函数来简单说明:

示例代码

上面这个xrange()函数提供了和PHP的内建函数range()一样的功能,但是不同的是range()函数返回的是一个包含值从1到100万的数组, 而xrange()函数返回的是依次输出这些值的一个迭代器, 而不会真正以数组形式返回。这种方法的优点是显而易见的,它可以让你在处理大数据集合的时候不用一次性的加载到内存中,甚至你可以处理无限大的数据流。当然,也可以不用通过迭代生成器来实现这个功能,而是可以通过继承Iterator接口实现。但通过使用迭代生成器实现起来会更方便,不用再去实现iterator接口中的5个方法了。

要从迭代生成器认识协程,理解它内部是如何工作是非常重要的。 迭代生成器是一种可中断的函数,在它里面的yield构成了中断点。还是看上面的例子,调用xrange(1,1000000)的时候, xrange()函数里代码其实并没有真正地运行,它只是返回了一个迭代器。如下图:

示例代码

这就解释了为什么xrange()叫做迭代生成器, 因为它返回一个迭代器, 而这个迭代器实现了Iterator接口。调用迭代器的方法一次, 其中的代码运行一次。

例如, 如果你调用$range->rewind(), 那么xrange()里的代码就会运行到控制流第一次出现yield的地方。而函数内传递给yield语句的返回值可以通过$range->current()获取。为了继续执行跌代生成器中yield后的代码, 你就需要调用$range->next()方法。这将再次启动生成器, 直到下一次yield语句出现。因此,连续调用next()和current()方法,你就能从生成器里获得所有的值,直到再没有yield语句出现。

对xrange()来说,这种情形出现在$i超过$end时,在这种情况下,控制流将到达函数的终点,因此将不执行任何代码。一旦这种情况发生,vaild()方法将返回假,这时迭代结束。

下图是使用PHP实现协程的一个案例:

示例代码

使用Swoole实现协程

Swoole在2.0开始内置协程(Coroutine)的能力,提供了具备协程能力IO接口(统一在命名空间Swoole\Coroutine\*)。Swoole可以为每一个请求创建对应的协程,然后根据IO的状态来合理的调度协程。

Swoole这种模式带来了以下优势:

  1. 开发者可以无感知的用同步的代码编写方式达到异步IO的效果和性能,避免了传统异步回调所带来的离散的代码逻辑和陷入多层回调中导致代码无法维护。

  2. 同时由于swoole是在底层封装了协程,所以对比传统的php层协程框架,开发者不需要使用yield关键词来标识一个协程IO操作,不再需要对yield的语义进行深入理解以及对每一级的调用都修改为yield,这极大的提高了开发效率。

Swoole现实协程的案例如下:

当代码执行到connect()和recv()函数时,swoole会触发进行协程切换,此时swoole可以去处理其他的事件或者接受新的请求。当此client连接成功或者后端服务回包后,swoole server会恢复协程上下文,代码逻辑继续从切换点开始恢复执行。整个过程不需要开发者去干预。

当然,Swoole实现协程不仅仅如上面所示方面,还有其他,具体的大家可以看看官方手册。

swoole官网:https://www.swoole.com

相关推荐

ubuntu单机安装open-falcon极度详细操作

备注:以下操作均由本人实际操作并得到验证,喜欢的同学可尝试操作安装。步骤一1.1环境准备(使用系统:ubuntu18.04)1.1.1安装redisubuntu下安装(参考借鉴:https://...

Linux搭建promtail、loki、grafana轻量日志监控系统

一:简介日志监控告警系统,较为主流的是ELK(Elasticsearch、Logstash和Kibana核心套件构成),虽然优点是功能丰富,允许复杂的操作。但是,这些方案往往规模复杂,资源占用高,...

一文搞懂,WAF阻止恶意攻击的8种方法

WAF(Web应用程序防火墙)是应用程序和互联网流量之间的第一道防线,它监视和过滤Internet流量以阻止不良流量和恶意请求,WAF是确保Web服务的可用性和完整性的重要安全解决方案。它...

14配置appvolume(ios14.6配置文件)

使用AppVolumes应用程序功能,您可以管理应用程序的整个生命周期,包括打包、更新和停用应用程序。您还可以自定义应用程序分配,以向最终用户提供应用程序的特定版本14.1安装appvolume...

目前流行的缺陷管理工具(缺陷管理方式存在的优缺点)

摘自:https://blog.csdn.net/jasonteststudy/article/details/7090127?utm_medium=distribute.pc_relevant.no...

开源数字货币交易所开发学习笔记(2)——SpringCloud

前言码云(Gitee)上开源数字货币交易所源码CoinExchange的整体架构用了SpringCloud,对于经验丰富的Java程序员来说,可能很简单,但是对于我这种入门级程序员,还是有学习的必要的...

开发JAX-RPC Web Services for WebSphere(下)

在开发JAX-RPCWebServicesforWebSphere(上)一文中,小编为大家介绍了如何创建一个Web服务项目、如何创建一个服务类和Web服务,以及部署项目等内容。接下来小编将为大...

CXF学习笔记1(cxf client)

webservice是发布服务的简单并实用的一种技术了,个人学习了CXF这个框架,也比较简单,发布了一些笔记,希望对笔友收藏并有些作用哦1.什么是webServicewebService让一个程序可...

分布式RPC最全详解(图文全面总结)

分布式通信RPC是非常重要的分布式系统组件,大厂经常考察的Dubbo等RPC框架,下面我就全面来详解分布式通信RPC@mikechen本篇已收于mikechen原创超30万字《阿里架构师进阶专题合集》...

Oracle WebLogic远程命令执行0day漏洞(CVE-2019-2725补丁绕过)预警

概述近日,奇安信天眼与安服团队通过数据监控发现,野外出现OracleWebLogic远程命令执行漏洞最新利用代码,此攻击利用绕过了厂商今年4月底所发布的最新安全补丁(CVE-2019-2725)。由...

Spring IoC Container 原理解析(spring中ioc三种实现原理)

IoC、DI基础概念关于IoC和DI大家都不陌生,我们直接上martinfowler的原文,里面已经有DI的例子和spring的使用示例《InversionofControlContainer...

Arthas线上服务器问题排查(arthas部署)

1Arthas(阿尔萨斯)能为你做什么?这个类从哪个jar包加载的?为什么会报各种类相关的Exception?我改的代码为什么没有执行到?难道是我没commit?分支搞错了?遇到问题无法在...

工具篇之IDEA功能插件HTTP_CLENT(idea2021插件)

工具描述:Java开发人员通用的开发者工具IDEA集成了HTTPClient功能,之后可以无需单独安装使用PostMan用来模拟http请求。创建方式:1)简易模式Tools->HTTPCl...

RPC、Web Service等几种远程监控通信方式对比

几种远程监控通信方式的介绍一.RPCRPC使用C/S方式,采用http协议,发送请求到服务器,等待服务器返回结果。这个请求包括一个参数集和一个文本集,通常形成“classname.meth...

《github精选系列》——SpringBoot 全家桶

1简单总结1SpringBoot全家桶简介2项目简介3子项目列表4环境5运行6后续计划7问题反馈gitee地址:https://gitee.com/yidao620/springbo...

取消回复欢迎 发表评论: