php swoole 协程 与 go 的协程比较

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

内容简介:在看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模型的协程方案,实现了无共享内存无锁的并发,可以匹配异步回调的性能。


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

查看所有标签

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

Web Design Handbook

Web Design Handbook

Baeck, Philippe de 编 / 2009-12 / $ 22.54

This non-technical book brings together contemporary web design's latest and most original creative examples in the areas of services, media, blogs, contacts, links and jobs. It also traces the latest......一起来看看 《Web Design Handbook》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具