11

在阅读了 Erlang 的轻量级进程后,我非常确定它们是“绿色线程”。直到我读到绿色线程和 Erlang 的进程之间存在差异。但我不明白。

实际的区别是什么?

4

3 回答 3

13

绿色线程可以直接在它们之间共享数据内存(当然需要同步)。

Erlang 不使用“绿色线程”,而是使用更接近“绿色进程”的东西:进程不直接共享数据内存,而是通过“复制”它来实现(即拥有源数据的独立副本)。

于 2009-12-22T15:47:03.333 回答
10

说 Erlang 进程不能直接共享数据内存,并且它们只能在彼此之间复制值,这种简化太过分了。这更多地描述了如何实现它,以及如何假装它已经实现。至少出于所有目的,除了性能问题。

Erlang 对程序员可以做的事情实施了一些语义限制。例如,值是不可变的,这意味着您在构造它们之后就无法更改它们。然后意识到多个 Erlang 进程访问内存中的相同值是完全可以的,因为无论如何都不能改变它。那时就不需要锁了。

在 Erlang/OTP 中执行此操作的值得注意的情况是:

  • 大型二进制文件(超过 64 字节)在特殊的二进制堆中进行引用计数,并且在消息传递时传递对该堆的引用。
  • 字面值被放置在一个特殊的内存区域中,所有引用它们的进程都引用同一内存区域中的值(但只要在消息中发送该值,就会在接收进程中进行复制)。
  • 每个节点作为一个全局原子表,原子值实际上是对该表的引用,这使得原子相等性测试非常有效(比较指针而不是字符串)。
  • erl -hybrid通过让进程在消息中使用时首先将值从进程堆复制到共享堆来组合进程堆和共享堆的实验设置。我发现了这个关于混合堆的线程,它也解释了这个概念的一些问题。

可以做的另一个技巧是实际改变值,但要确保它不可见。这是为了进一步解释不可变值是一种语义限制。

这些是 OTP/Erlang 实际会改变值的一些示例:

  • 处理二进制语法的“最近”(R12)优化允许您附加到二进制文件的末尾,实际上不会构造一个添加了新尾部的完整新二进制文件。
  • 据说,具有立即 set_element 的新构造的元组可以或曾经被编译器翻译,以实际更改元组的元素。

这些优化基于这样的理论:“如果一棵树倒在森林里,而没有人听到它,它真的会发出声音吗?” . 也就是说,引用不能转义到要变异的对象。因为那时可以观察到它已经改变了。

这就是 Erlang 语义的真正意义所在,事情不应该因为其他进程正在做的事情而改变。我们称之为共享状态,我们一点也不喜欢它。

另一个过分的简化是说 Erlang 没有副作用。但如果有人问过,那是另一个问题。

于 2009-12-22T18:42:04.320 回答
6

当人们反对称 Erlang 的进程为“绿色线程”时,他们并不是在反对“绿色”部分,而是在反对“线程”部分。

线程和进程之间的区别基本上是,线程只有自己的指令指针,但共享其他所有内容(尤其是状态、内存、地址空间)。OTOH 流程是完全隔离的,不共享任何内容。

Erlang 的进程不共享任何东西,因此它们是真正的进程。但是,它们通常以“绿色”方式实施。因此,从技术上讲,它们是“绿色流程”。

当我想强调轻量级实现时,我通常称它们为“绿色线程”,当我想强调无共享语义时,我称它们为“进程” 。这样我就不必解释我所说的“绿色流程”是什么意思了。

于 2009-12-22T21:09:58.300 回答