php swoole 协程 与 go 的协程比较

栏目: PHP · 发布时间: 5年前

内容简介:在看swoole的时候,看到php 定义协程的方式是此时吓我一大跳,因为之前写过golang,go里定义协程的方式是难道是php 这里又是抄袭了 go???????抱着好奇的心情展开了调查

在看swoole的时候,看到 php 定义协程的方式是

go(function () {
    echo "hello wangbaojin \n";
});

此时吓我一大跳,因为之前写过golang,go里定义协程的方式是

go func

难道是php 这里又是抄袭了 go???????抱着好奇的心情展开了调查

########################################################

各种语言的协程支持情况

C++ 可以通过 Boost.Coroutine 库实现协程。

Java 不支持协程

Python 3.5 加入了 async def 对协程的支持,但是 Python 的 协程是在方法定义时就确定了,被定义协程的方法不能当做普通方法来使用,而 Go 语言

swoole介绍

Swoole 使用纯 C 语言编写,提供了 PHP 语言的异步多线程服务器,异步 TCP/UDP 网络客户端,异步 MySQL,异步 Redis,数据库连接池,AsyncTask,消息队列,毫秒定时器,异步文件读写,异步DNS查询。 Swoole内置了Http/WebSocket服务器端/客户端、Http2.0服务器端。

除了异步 IO 的支持之外,Swoole 为 PHP 多进程的模式设计了多个并发数据结构和IPC通信机制,可以大大简化多进程并发编程的工作。其中包括了并发原子计数器,并发 HashTable,Channel,Lock,进程间通信IPC等丰富的功能特性。

Swoole2.0 支持了类似 Go 语言的协程,可以使用完全同步的代码实现异步程序。PHP 代码无需额外增加任何关键词,底层自动进行协程调度,实现异步。

swoole协程与go的协程对比

区别 swoole协程 go 协程
底层原理 单进程 多线程
CSP理论 单进程 简单 / 不用加锁 / 性能也高 MPG模型

MPG模型

php swoole 协程 与 go 的协程比较

image.png

CSP理论

SP模型是上个世纪七十年代提出的,用于描述两个独立的并发实体通过共享的通讯 channel(管道)进行通信的并发模型。 CSP中channel是第一类对象,它不关注发送消息的实体,而关注与发送消息时使用的channel。

Golang CSP

Golang 就是借用CSP模型的一些概念为之实现并发进行理论支持,其实从实际上出发,go语言并没有,完全实现了CSP模型的所有理论,仅仅是借用了 process和channel这两个概念。process是在go语言上的表现就是 goroutine 是实际并发执行的实体,每个实体之间是通过channel通讯来实现数据共享。

Channel

Golang中使用 CSP中 channel 这个概念。channel 是被单独创建并且可以在进程之间传递,它的通信模式类似于 boss-worker 模式的,一个实体通过将消息发送到channel 中,然后又监听这个 channel 的实体处理,两个实体之间是匿名的,这个就实现实体中间的解耦,其中 channel 是同步的一个消息被发送到 channel 中,最终是一定要被另外的实体消费掉的,在实现原理上其实是一个阻塞的消息队列。

Goroutine

Goroutine 是实际并发执行的实体,它底层是使用协程(coroutine)实现并发,coroutine是一种运行在用户态的用户线程,类似于 greenthread,go底层选择使用coroutine的出发点是因为,它具有以下特点:

用户空间 避免了内核态和用户态的切换导致的成本

可以由语言和框架层进行调度

更小的栈空间允许创建大量的实例

可以看到第二条 用户空间线程的调度不是由操作系统来完成的,像在 java 1.3中使用的greenthread的是由JVM统一调度的(后java已经改为内核线程),还有在 ruby 中的fiber(半协程) 是需要在重新中自己进行调度的,而goroutine是在golang层面提供了调度器,并且对网络IO库进行了封装,屏蔽了复杂的细节,对外提供统一的语法关键字支持,简化了并发程序编写的成本。

附 实现高并发的几种方式

多线程

提起并发编程,最常见的就是多线程编程。线程是操作系统能够进行调度的最小单位,共享同一进程的数据和资源,有内核线程和用户线程之分,由操作系统或用户进程调度。多线程的程序可以利用多核CPU,并行地处理多个任务。随着并发量增大,线程数增加,多线程的并发模型面临一些问题。

内存占用

64位JVM线程默认栈空间是1M,启动1024个线程理论上消耗1G的栈空间。由于线程需要内存较多,为避免内存耗尽,应用程序不应该大量创建线程。

线程调度

操作系统对线程进行调度也需要成本。线程挂起前会保存线程上下文到栈空间,再切换到可执行线程。线程数很多时,线程上下文切换会导致CPU开销变大。

使用线程池技术可以对多线程并发进行优化,线程池实现线程复用,避免频繁创建新线程和线程切换,控制了线程数量,减少了内存的消耗。但是在竞争共享数据的时候,需要用加锁来保护共享数据,这样也降低了程序的并发效率。

异步回调

为了充分利用CPU,不让线程空等待,在线程阻塞的时候,注册一个回调方法,让当前线程不再阻塞,去处理新的请求。等结果准备好,调度器把结果传给回调方法,在回调方法中继续处理结果。然而回调方法并不在发起请求的线程里执行。

异步回调的缺点是所谓的callback hell。原本顺序同步的执行逻辑拆分到回调方法中,而且回调方法中可能再嵌套回调方法。这种写程序的方式还是让很多 程序员 不太习惯。异步回调的典型实现是NodeJS,目前也有一些第三方模块将异步代码同步化。

协程(纤程)

协程(纤程)也是一种异步方案。在代码IO阻塞时,当前协程让出CPU执行权,让其它协程执行。待IO操作完毕,阻塞的协程继续执行。虽然代码是异步执行,但写代码看起来像是同步的。协程是用户态的轻量级线程,现在的机器可以启动百万数量的协程。支持协程的编程语言实现了协程的调度器,提供了channel机制进行协程间通信(CSP模型中消息传递的实现)。基于CSP模型的协程方案,实现了无共享内存无锁的并发,可以匹配异步回调的性能。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

剑指Offer

剑指Offer

何海涛 / 电子工业出版社 / 2012-1 / 45.00元

《剑指Offer:名企面试官精讲典型编程题》剖析了50个典型的程序员面试题,从基础知识、代码质量、解题思路、优化效率和综合能力五个方面系统整理了影响面试的5个要点。全书分为7章,主要包括面试的流程,讨论面试流程中每一环节需要注意的问题;面试需要的基础知识,从编程语言、数据结构及算法三方面总结了程序员面试的知识点;高质量的代码,讨论影响代码质量的3个要素(规范性、完整性和鲁棒性),强调高质量的代码除......一起来看看 《剑指Offer》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具