go许式伟 如何看待许式伟谈Go Erlang并发编程差异?

2018-04-05
字体:
浏览:
文章简介:Erlang为什么没有锁呢?实际上Erlang的服务器是单进程(Process)的,是逻辑上就无并发的东西.一个Process就是一个执行体,所以Erlang的服务器和Go的服务器不一样,Go的服务器必然是多进程(goroutine)一起构成一个服务器的,每个请求一个独立的进程(goroutine).但是Erlang不一样,一个Erlang服务器是一个单进程的东西,既然是一个单进程的首先所有的并发请求都进入了进程邮箱(后面会谈这个进程邮箱),然后这个服务器从进程邮箱里面取邮件(请求的内容)然后处

Erlang为什么没有锁呢?实际上Erlang的服务器是单进程(Process)的,是逻辑上就无并发的东西。一个Process就是一个执行体,所以Erlang的服务器和Go的服务器不一样,Go的服务器必然是多进程(goroutine)一起构成一个服务器的,每个请求一个独立的进程(goroutine)。

但是Erlang不一样,一个Erlang服务器是一个单进程的东西,既然是一个单进程的首先所有的并发请求都进入了进程邮箱(后面会谈这个进程邮箱),然后这个服务器从进程邮箱里面取邮件(请求的内容)然后处理,所以Erlang的单个服务器并没有并发的请求,这个是他不需要锁的根本原因,其实并不是因为它没有变量,变量不可变这些。

因为大家都知道单线程的服务器一定是没有锁的。那么可能会有人问,那Erlang怎么做高并发呢?其实是两点:第一是每个Erlang物理的进程会有很多的服务器,每个服务器相互是无干扰的,它们可以并发。第二是单服务器想要高并发怎么办?Erlang对这个问题的回答就是请异步IO。

最后一个细节是我刚刚讲过的次重要的概念,它是 Erlang的进程邮箱,所有发给Erlang进程的消息都会发到这个进程邮箱,Erlang提供邮箱收发消息的元语。Go则提供了channel这样的通讯设施,这个channel可以轻易创建很多个,然后用它进行进程通讯。相比之下,Go的消息机制抽象更轻盈。消息队列和进程是完全独立的设施。

那么最后一个问题,Erlang中是不是可以实施Go的并发模型?在Go里面实施Erlang的并发模型是比较容易的,但是反过来想Erlang里面可不可以实现Go的并发模型呢?原则上是不能。因为在Erlang当中进程不能实现共享状态,这个是他反对锁的最重要的基点。

进程不能共享状态,所以不用锁,但其实我认为这个是最大的问题,为什么呢?因为Erlang收到请求以后没有办法创建一个子的执行体,然后让它处理某一个具体的请求不用再管它。

但是Erlang里面进程没有共享状态,你要改服务器状态必须用异步IO的方式,把事情做了再把消息扔给服务器对他说你自己改状态。通过消息改服务器状态,这个成本是比较大的,而且带来了很多问题。

所以我认为Erlang的用消息改这个状态是不好的做法,绕了一大圈没有本质改变任何的东西。当然,如果我在Erlang里面非要做到Go的并发模型也可以,这需要对Erlang做一个阉割,如果我们让Erlang的服务器都无状态的话,是可以实施Go的并发模型。

什么样的服务器是无状态的?大家可能很容易想到PHP服务器。它把状态交给所有的外部的存储服务,由存储服务来维持状态。如果说Erlang的服务器是无状态的是可以实施Go的并发模型,因为所有的状态都通过修改外部的存储。

但是这样的话Erlang程序员肯定是很伤心,看起来Erlang语言并没有带来什么实质性的好处。所以我的结论是:是时候放弃Erlang了。