Erlang Processes vs Java Threads
我正在读Saša Jurić的“Elixir in Action”一书,在第一章中说:
Erlang 进程彼此完全隔离。它们不共享内存,一个进程的崩溃不会导致其他进程的崩溃。
Java线程不是也是如此吗?我的意思是,当Java线程崩溃时,它也不会使其他线程崩溃 - 特别是如果我们正在查看请求处理线程(让我们从此分解中排除该线程)main
我正在读Saša Jurić的“Elixir in Action”一书,在第一章中说:
Erlang 进程彼此完全隔离。它们不共享内存,一个进程的崩溃不会导致其他进程的崩溃。
Java线程不是也是如此吗?我的意思是,当Java线程崩溃时,它也不会使其他线程崩溃 - 特别是如果我们正在查看请求处理线程(让我们从此分解中排除该线程)main
在我之后重复:“这些是不同的范式”
大声说20次左右 这是我们此刻的口头禅
如果我们真的必须比较苹果和橙子,让我们至少考虑一下“成为水果”的常见方面在哪里相交。
Java“对象”是Java程序员的基本计算单元。也就是说,对象(基本上是具有手臂和腿的结构,其封装比C++中更严格)是您用来对世界进行建模的主要工具。你认为“这个对象知道/拥有并在它上面执行,携带它所到之处,并且可以通过调用定义为其公共接口一部分的函数/方法与其他对象进行通信。它是一个名词,这个名词可以做一些事情。也就是说,你把你的思维过程围绕着这些计算单元。默认情况是对象之间发生的事情按顺序发生,并且崩溃会中断该序列。它们被称为“对象”,因此(如果我们忽略Alan Kay的原始含义),我们得到“对象导向”。Data {X,Y,Z}
Functions {A(),B(),C()}
Data
Erlang“进程”是Erlang程序员的基本计算单元。过程(基本上是一个在自己的时间和空间中运行的独立顺序程序)是Erlanger对世界进行建模的主要工具(1)。与Java对象定义封装级别的方式类似,Erlang进程也定义了封装级别,但在Erlang的情况下,计算单元彼此完全切断。您不能在另一个进程上调用一个方法或函数,也不能访问其中的任何数据,一个进程甚至不能在与其他任何进程相同的计时上下文中运行,并且不能保证消息接收相对于可能发送消息的其他进程的顺序。它们也可能完全位于不同的行星上(而且,想想看,这实际上是合理的)。它们可以彼此独立地崩溃,其他进程只有在故意选择受到影响时才受到影响(甚至这涉及消息传递:本质上是注册以接收来自死亡过程的遗书,这本身并不能保证以相对于整个系统的任何顺序到达, 您可能会选择或不选择对此做出反应)。
Java直接在复合算法中处理复杂性:对象如何协同工作以解决问题。它被设计为在单个执行上下文中执行此操作,Java 中的缺省情况是顺序执行。Java中的多个线程表示多个正在运行的上下文,并且是一个非常复杂的主题,因为不同计时上下文中的活动对彼此(以及整个系统:因此防御性编程,异常方案等)都有影响。在Java中说“多线程”意味着与在Erlang中不同的东西,事实上,这在Erlang中甚至从未说过,因为它始终是基本情况。请注意,Java线程意味着与时间有关的隔离,而不是内存或可见引用 - Java中的可见性是通过选择私有的和公共的来手动控制的;系统的通用可访问元素必须设计为“线程安全”和可重入,通过排队机制按顺序排列,或者采用锁定机制。简而言之:调度是线程/并发 Java 程序中手动管理的问题。
Erlang 在执行时序(调度)、内存访问和引用可见性方面分离了每个进程的运行上下文,并且通过完全隔离算法来简化算法的每个组件。这不仅仅是默认情况,这是此计算模型下唯一可用的情况。这是以永远不知道任何给定操作的顺序为代价的,一旦你的一部分处理序列越过了消息障碍 - 因为消息本质上都是网络协议,并且没有可以保证在给定上下文中执行的方法调用。这类似于为每个对象创建一个JVM实例,只允许它们跨套接字进行通信 - 这在Java中会非常麻烦,但这是Erlang设计的工作方式(顺便说一句,这也是编写“Java微服务”概念的基础,如果抛弃流行语往往带来的面向Web的包袱 - Erlang程序是, 默认情况下,为微服务群)。这一切都是关于权衡的。
这些是不同的范式。我们可以找到的最接近的共性是说,从程序员的角度来看,Erlang进程类似于Java对象。如果我们必须找到一些东西来比较Java线程...好吧,我们根本不会在Erlang中找到这样的东西,因为在Erlang中没有这种可比较的概念。打败一匹死马:这些是不同的范式。如果你在Erlang中写了一些重要的程序,这将变得显而易见。
请注意,我说的是“这些是不同的范式”,但甚至没有触及OOP与FP的话题。“用Java思考”和“用Erlang思考”之间的区别比OOP与FP更基本(事实上,人们可以为Erlang VM编写一种像Java一样的OOP语言 - 例如:Erlang中OOP对象的实现。
虽然Erlang的“面向并发”或“面向过程”的基础确实更接近Alan Kay在创造术语“面向对象”(2)时的想法,但这并不是重点。Kay得到的是,可以通过将计算机切割成离散的块来降低系统的认知复杂性,而隔离是必要的。Java以一种基本上仍然是过程性的方式实现了这一点,但是围绕一种特殊的语法构建代码,而不是称为“类定义”的高阶调度闭包。Erlang 通过将每个对象的运行上下文拆分起来来实现此目的。这意味着Erlang的东西不能互相调用方法,但Java的东西可以。这意味着Erlang的东西可以孤立地崩溃,但Java的东西不能。这种基本差异产生了大量的含义 - 因此是“不同的范式”。权衡。
脚注:
绝对不是。Java 中的所有线程共享相同的地址空间,因此一个线程可以丢弃另一个线程拥有的内容。在Erlang VM中,这是不可能的,因为每个进程都与其他所有进程隔离。这就是他们的全部意义。每当您希望一个进程对另一个进程中的数据执行某些操作时,您的代码都必须向另一个进程发送消息。进程之间唯一共享的是大型二进制对象,这些对象是不可变的。