在了解了Erlang的轻量级进程后,我相信它们是“绿色线程”(green threads)。直到我了解到绿色线程和Erlang进程之间存在差异,但我并不理解这些差异。
那么,这些实际上的差异是什么呢?
在了解了Erlang的轻量级进程后,我相信它们是“绿色线程”(green threads)。直到我了解到绿色线程和Erlang进程之间存在差异,但我并不理解这些差异。
那么,这些实际上的差异是什么呢?
绿色线程可以直接共享数据内存(当然需要同步)。
Erlang不使用“绿色线程”,而是使用更接近“绿色进程”的东西:进程不能直接共享数据内存,但可以通过“复制”它来进行共享(即拥有源数据的独立副本)。
简单地说,Erlang进程之间不能直接共享数据内存、只能在彼此之间传递值的说法是一种过于简化的描述。这更多是一种针对实现方式的描述,以及如何假装已经实现了这种方式,至少在除了性能问题之外的所有情况下。
Erlang对程序员的操作进行了一些语义限制。例如,值是不可变的,这意味着构造后无法更改它们。因此,我们可以轻松地让多个Erlang进程访问内存中的相同值,因为它们都无法改变它。这时就不需要使用锁了。
以下是在Erlang/OTP中完成此操作的显著情况:
erl -hybrid
设置将进程堆和共享堆结合起来,在使用消息时,进程首先将值从进程堆复制到共享堆中。我在这里找到了一个有关混合堆的线程,该线程还解释了一些与该概念相关的问题。另一个技巧是实际上更改值,但确保它不可见。这进一步解释了不可变值是一种语义限制。
以下是OTP/Erlang实际上会更改值的一些示例:
这些优化基于这样的理论:“如果一棵树倒在森林里,没有人听到,它真的发出声音吗?”。也就是说,引用不能逃逸到要被修改的对象中。否则,就会观察到它已经发生了变化。
这才是 Erlang 语义的关键所在,事物不应因其他进程的操作而产生副作用。我们称之为共享状态,我们非常不喜欢。
另一个过度简化的观点是,Erlang没有副作用。但如果有人问起,那就留着下次回答吧。