【51CTO精选译文】前日,Akka 0.6发布了。Akka是一个基于Actor的框架,提供Scala API和Java API,目标是“通过Actor实现更简单的伸缩性,容错力,并发以及远程操作”。
本篇文章的主题是Actor。对于不太了解Actor的读者们,可以先参考一下老赵的这篇《Actor模型的本质》。简单的说,Actor是一种天生为并行编程而存在的模型,在很多编程语言中都采用了这种模型,比如C#,Erlang以及Scala。本文是Code-o-matic博主Dimitris Andreou针对Scala的Actor模型展开的思考。
51CTO编辑推荐:Erlang的Actor回顾 顺畅的使用C# Actor
有人在Scala邮件列表的讨论中建议直接对比actors和锁的使用。下文是我的讨论,前面部分只是作为一种回应,而最后我总结了不少当前对于actor编程模型的关注点和问题。
将actors和底层并发编程(比如锁)做对比具有误导性。它不是这样一种情况:存在一些actors,它们之后是巨大的空白,然后是一些锁——然后我们不得不做出一些极端的选择。两者之间涉及更多的东西。例如,一台虚拟机中,在阻塞队列(或者,不久之后将成为的传输队列)的顶端实现消息传递是非常烦琐的。目前已经有executor框架,以及fork/join框架来提供线程池或者细粒度(fine-grained)的并行(parallelism)机制。(51CTO编辑推荐阅读:Java 7的细颗粒并行化)
我要说的是,actors提供了一种简单化的、比直接使用底层工具更简洁优雅的编程模型。在其内核中,典型的actors是一种伴随阻塞队列(邮箱)的运行接口,而反应程序是事件的监听者。正如Haller/Odersky论文中指出的那样,actors的优势在于它们能够将基于线程和基于事件的模型统计起来——人们也可以在相同的架构下使用这两种模型,或者对它们进行组合。这种编程模型目前正处于起步阶段,还需要编程人员去探索以找到最佳的使用案例,并充分的理解它。颇为重要的是,你有必要准备一本“Effective Actors”这种类型的书。Actors编程很容易误入歧途,尤其是对于那些试图进行类MPI编程却被搞得晕头转向的初学者而言更是如此。死锁仍然存在(actors可能会永久等待一个不会到达的消息),竞争条件也可能出现(actors可能在真正的响应到达之前放弃等待),它不会像常规并发编程那样,其可疑之处不会奇迹般的消失。(注明:根据JCiP命名规则(51CTO编辑注:JCiP即Java Concurrency in Practice,实用Java并发),我将最后一种情况归为竞争条件或许是一个错误,因为它更像是一种数据竞争)
此外,简化编程也必须付出代价,探讨其对性能的影响变得不再像以前那么容易,至少对我而言如此。例如:假定scala actors依赖于ForkJoinScheduler(也就是使用fork/join架构), 此处源自ForkJoinPool中的javadocs的引用将会很有意思:
ForkJoinPool在创建时会被指定一个并行等级(目标池的大小),该等级通过动态添加、挂起、恢复线程的方法来维持,即使一些任务正在等待其它任务也是如此。然而,在阻塞式IO或者非托管的异步系统中,这种调整没有被实现。
这就产生一些很明显、但我却很难告诉你答案的问题:
1. actors使用(阻塞式)IO会对性能产生什么影响?(我还没有看到提供给actors用户的类似警告)
2. 既然我们根据javadoc已经知道任务不会被加入,而receive()的阻塞式系统调用会陷入非托管的同步系统中,那么这对我们而言又意味着什么呢?
#t#因此,简单化也似乎意味着以隐藏可能的重大优化作为代价,就像一个需要阻塞以加入子任务的线程一样,在其等待期间继续运行以及执行其它任务。
我不能确定最终的结论是什么。若顺利的话,3-4年内社区在这一方面的编程经验将会大大增加,我们将了解如何才能更好的使用这种很炫的工具,也将会知道什么时候改使用底层的并发服务程序。就我个人而言,截至目前为止,尽管我很希望使用actors,但底层工具的运用让我如鱼得水,因为我可以更容易分析我的代码的性能特征。很希望有人能够写一本优秀的Scala actors书籍——虽然目前并发的书也不错,但因为Scala还很新,所以这些数据关于actors的往往只有一章。读者若想了解除基础知识之外的东西,这些书籍所涵盖的内容还远远不够。
【51CTO.com译稿,非经授权请勿转载。合作站点转载请注明原文译者和出处为51CTO.com,且不得修改原文内容。】
原文:Thoughts on Actors 作者:Dimitris Andreou