文章大概翻译如下:
我真的希望人们停止在JVM上建设Actor框架。我知道,在过去我自己也有这样做。无一例外,这些项目远远低于他们的预期目标。
然而,让我们退一步。到底是Actor,为什么每个人都这么热衷于它们?Actor模型描述了一组为了避免并发编程的常见问题的公理,并在学术界提供了一种并行计算的理论分析。具体实现可能大幅不同于他们的定义,但是最基本的Actor模型公理:
1.所有Actor状态是Actor本地的,外部无法访问。
2.Actor必须只有通过消息传递进行通信。可变信息不能别名。
3.一个Actor可以响应消息:推出新Actor,改变其内部状态,或将消息发送到一个或多个其他参与者。
4.Actor可能会堵塞自己,但Actor不应该堵塞它运行的线程。
Actor的主要优势围绕人体工程学并发性。并发系统是经典的困难,因为没有顺序能够保证内存突变(程序员无法通过代码指定线程执行顺序,因为线程只听命于CPU调度),告诉哪些线程可能会执行一个给定的一段代码不可避免地变得很难。由于并发马虎出现的错误是出了名的难以解决,这些都是由于线程调度的不可预测性
通过Actor编程模型,大大缩小了最愚蠢设计导致的不良并发性。Actor和他们的服务员消息队列提供本地顺序保证,由于Actor只能一次处理一个消息,你得到了Actor内部本地状态的隐式锁定。Actor的轻量级特性也意味着它们可以产生的方式与问题域是1:1,减轻程序员需要多路复用的线程池。
..
不幸的是,Actor框架在JVM上不能充分约束编程环境避免并发缺陷,毕竟,你只是在普通线程内编写一个POJO对象(或scala clojure)。没有什么实际的方法限制代码能做什么,除非它明确不允许调用其他代码或循环。因此,即使使用字节码编织来实现协作的Actor框架在多任务时也不能完全保证非阻塞。这一点还是值得重复:没有根本改变JVM是如何工作的内部原理,你就不能保证任意一段代码不会被堵塞。
他们经常使用字节码bytecode编制weaving调整你的代码,Actor底部实现经常使用Java的 fork/join框架,其有臭名昭著的开销 ,尤其是当它涉及到小计算时,与vanilla 香草线程池相比是极其复杂的。Actor系统应该使并行计算很简单,但在JVM上轻量级线程系统我看过一点也不简单。
为了免得你认为我是一个Actor怀恨者,我真正喜欢的面向Actor编程。我一直是多年热情的Erlang程序员了,我曾经真正参加令人兴奋的添加此范式到Java的活动。然而,我现在相信,平台不支持这些轻量级并发库将永远是将所有努力打了一个水漂。我不是唯一持有这种观点的人。
我们不应该信任厂商推动的什么宣言(Reactive宣言),用几十年的古老的部落的线程实现是误导的。我们应该建立尽可能简单的系统来解决我们的问题,以及如何测量他们,最有效地使用我们的机器。