在不允许修改变量的语言中,维护状态的简单动作需要一个单独的执行上下文(大多数人将其称为线程,而Erlang则将其称为进程)。基本上,一切都是工人。
考虑以下这个Erlang函数,该函数维护一个计数器:
counter(Value) ->
receive % Sit idle until a message is received
increment -> counter(Value + 1); % Restart with incremented value
decrement -> counter(Value - 1); % Restart with decremented value
speak ->
io:fwrite("~B~n", [Value]),
counter(Value); % Restart with unaltered value
_ -> counter(Value) % Anything else? Do nothing.
end.
在像C ++或Java这样的常规OO语言中,您可以通过创建一个带有私有类成员的类,用于获取或更改其状态的公共方法以及每个计数器的实例化对象来实现。Erlang用进程替换了实例化对象的概念,用消息替换了方法的概念,并通过尾部调用来维护状态,这些尾部调用使用组成新状态的任何值重新启动函数。该模型以及大多数Erlang的存在理由的隐藏优点是,该语言通过使用消息队列自动序列化对计数器值的访问,从而使并发代码非常容易实现,并且具有高度的安全性。
您可能已经习惯了上下文切换很昂贵的想法,从主机OS的角度来看,这仍然是正确的。Erlang运行时本身是一个经过微调的小型操作系统,因此在自己的进程之间进行切换是快速而高效的,同时还可以将OS所做的上下文切换次数降至最低。因此,拥有成千上万的流程不是问题,应予以鼓励。