Actors in Scala(Scala中的Actor)(预打印版) 第二章 Messages All the Way Up (A)

Actors in Scala(Scala中的Actor)(预打印版) 第二章 Messages All the Way Up (A)

张贵宾

guibin.beijing@gmail.com

2011.10.08


第二章 Messages All the Way Up(始终都是消息)

基于Actor的编程力争将无处不在的并发世界建模成为数不多的简单抽象。在一头栽入Scala的actor库之前,很有必要简单回顾一下最常用的Actor编程模型。Actor的库函数实现了这些特性,与此同时象许多Scala API一样,Actor的API也在不断的演进,并且将来的版本将会提供更多的能力。在即将介绍的Actor编程模型的概览中,我们都引用的是Scala actors已经实现的功能,并且当与通用的Actor相关时,我们会指出Scala actors和通用Actor模型的区别。


2.1 Control flow and data flow(控制流和数据流)

Actor编程模型的设计者是从为并发系统的控制流定义合适的抽象开始设计Actor的。非正式的讲,程序的控制流是指程序在执行下一步指令时的选择。分支,比如switch和case语句,也就是决定将从一个方法调用时返回什么结果,这些都是控制流。除了微不足道的程序之外,程序都包含控制流。


顺序程序(sequential programs)的开发者不会认为控制流是一个有问题的任务,毕竟我们平常没有太多的考虑这些基本程序结构的含义,便例行公事般的写if,whilefor表达式。然而并发会使得控制流更难推断。这是由于控制流经常会依赖一些逻辑、数据或者程序的内嵌状态。




在小程序中,数据和使用这些数据的控制结构相互间的距离很接近,甚至就在同一个对象中。当程序的体积增长时,控制流的决定需要去查询一些定义在程序其他部分的数据或者程序状态。比如,下面的表达式需要访问currentSpeeddesiredSpeed变量:


if (currentSpeed != desiredSpeed) 
  changeSpeed(desiSrpeed - currentSpeed)
else
  maintainSpee ()


currentSpeeddesiredSpeed都定义在if else控制结构之外,也许甚至定义在包含这个控制表达式的方法或者对象之外。相似的,实现currentSpeeddesiredSpeed的方法可以访问这两个变量,而且定义在程序其他部分的程序也能访问、修改这两个状态。因此这样的程序需要访问其他对象暴露和共享的程序状态。在上面的这个例子中,比如SpeedMonitor对象可能有一个public的currentSpeed的访问方法,这个方法可以被程序中的其他对象调用。currentSpeed就变成了全局可见的程序状态。

对于不同对象可见的全局的程序状态,如果仅仅是单线程访问这个状态,那就没有什么问题。但是如果许多并行执行的线程需要访问全局可见的状态,此时开发者就需要非常小心的同步去访问(synchronize access)控制状态的那个对象。


正确的同步访问共享数据并不难,但是这样做会降低系统的并发处理能力。其原因如下,当并发程序运行时,从概念上讲有两种不同类型的变化发生:首先,当不同的线程都从程序的开始处执行,然后基于程序的控制流蜿蜒的从各种可能的路径执行下去。这些线程会依次修改那些掌控程序状态的变量。你可以认为这些状态的变化定义了程序的数据流。开发者必须非常小心的确认程序数据流中的每一处可以修改的地方接下来会不会影响其他正在执行的线程,并且要提防意外的副作用。


一个已经被证明的能确避免令人保讨厌的数据流和控制流冲突的有效方法是:使并发执行的线程顺序访问程序的数据流。使用诸如锁(lock)、监视器(monitor)和信号(semaphores)这些特殊的结构,开发者能够严格的指定影响数据流的线程的执行顺序。有关Semaphore的细节,请参考Semaphore的API


有了java.util.concurrent包之后,使用Java或者Scala定义这样的顺序访问方式就非常的简单了。


虽然顺序全局可见的程序状态能帮助我们定义正确的程序行为,但是他会削弱并发执行带来的一系列优势:比如在前面章节提到的,并发的优势在于对程序蜿蜒曲折的访问程序状态的顺序没有限制(然而使用Semophore这些特殊的结构之后,就变得有序但是低效了)。实际上,同步是把一部分程序变成了串行执行,这由于在同一时刻仅能有一个线程访问全局的或者共享的状态。确实,如果整个程序的控制结构都依赖于全局可见的状态,那除了串行访问之外,就基本没有办法避免不正确的行为了。


Actor模型的一个主要的贡献就是以最小程度依赖全局程序状态的方式定义了控制结构,即所有的需要控制流程决定的状态和相关知识都与最终做决定的对象在同一个对象中。这些对象依次控制数据流,或者基本基于本地可见的数据来控制数据流。这个(使得共享数据、状态与控制流程在一起的)地点规则使得程序中的控制流和数据流形影不离、不可分割,进而减少了同步的需求,这反过来使得潜在的并发(性能)最大化。


虽然基于Actor的系统认为全局(可见的)状态是恶魔(即全局状态是基于Actor系统所摒弃的),但是在实际中一些控制结构仍然需要访问全局可见的状态,最近新添加的Scala的Actors中的一些库函数使得在Actor的上下文中推理这样的共享状态变得更容易。在本书中我们将着重强调Scala的这些特性。




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值