<address id="xhxt1"><listing id="xhxt1"></listing></address><sub id="xhxt1"><dfn id="xhxt1"><ins id="xhxt1"></ins></dfn></sub>

    <thead id="xhxt1"><dfn id="xhxt1"><ins id="xhxt1"></ins></dfn></thead>

    软件事务内存导论(三)用Akka/Multiverse STM实现并发

    声明:本文是《Java虚拟机并发编程》的第六章,感谢华章出版社授权并发编程网站发布此文,禁止以任何形式转载此文。

    用Akka/Multiverse STM实现并发

    上面我们已经学习了如何在Clojure里使用STM,我猜你现在一定很好奇如何在Java代码中使用STM。而对于这一需求,我们有如下选择:

    • 直接在Java中使用Clojure STM。方法非常简单,我们只需将事务的代码封装在一个Callable接口的实现中就行了,详情请参见第7章。
    • 喜欢用注解(annotation)的开发者可能会更倾向于使用Multiverse的STM API.
    • 除了STM之外,如果我们计划使用角色(actor),那么还可以考虑选择Akka库。

    Multiverse是由Peter Veentjer主持开发的一个基于Java的STM实现。通过这个库,我们可以在Java代码中使用注解来标识事务边界。我们既可以用@TransactionalMethod注解将单个的方法标记为事务性的,也可以用@TransactionalObject注解将一个类的所有方法都标记为事务性的。为了与其他JVM上的语言进行集成,Multiverse还提供了一组丰富的API来控制事物的开始和结束。

    Akka是一个由Jonas Boner主持开发的一个基于Scala的解决方案,该方案可以用于包括Java在内的很多其他运行于JVM上的语言。Akka不但提供了STM和基于角色(actor)的并发方案,还提供了将二者混合使用的选项。此外,Akka使用Multiverse作为其STM的实现并提供了ACI(ACID的子集)特性。

    Akka的性能非常棒,并且由于它既支持STM又支持基于角色(actor)的模型(详情请参见第8章),本章我们将会用它来实现演示Java STM的例子。


    Akka/Multiverse中的事务

    Akka的Java版采用了Multiverse的Clojure风格的STM。与Java那繁冗的代码风格相比,Clojure风格的Akka不会强迫我们在能够修改可变实体之前就创建事务。如果我们没有主动提供事务,则Akka/Multiverse就会自动把访问请求封装在一个事务中。所以当我们处于事务之中时,Akka的ref与Clojure的ref的表现是相同的;而当我们位于事务之外时,Akka ref的表现则更像是Clojure的atom?;痪浠八?,想要使变更同步且有序就必须使其在事务中完成,否则变更将是同步但无序的。在任何情况下,Akka都会保证对于ref的更改是原子的、隔离的且一致的,并同时提供了不同等级的协调粒度。

    在Akka中,我们既可以用写代码的方式在事务层对事务进行配置,也可以通过配置文件在应用程序/JVM层进行配置。例如,我们可以将一个事务定义为只读(readonly),于是Akka将不再允许任何位于该事务范围内的Akka引用被修改。这样做的好处是,如果我们将一些不可变的事务设置为只读,则程序性能将会得到一定的提升。除此之外,我们还可以控制在冲突情况下事务的最大重试次数。当然,还有很多其他参数可供我们配置,详情请参阅Akka的帮助文档。

    Akka扩展了Multiverse中的嵌套事务(请参见6.9节),所以我们能够很方便地在事务中调用启动其他事务的函数。默认情况下,这些内部事务或嵌套事务都是与其外部事务融为一体的。

    使用Akka引用和事务

    Clojure中的ref是在语言层定义的,而 Akka是一个公共类库所以不能依赖任何现有语言的支持。所以Akka在其akka.stm包中提供了一个托管事务引用(managed transactional reference)Ref和一些为原始类型而设的特殊类,如IntRef、LongRef等。Ref(以及所有原始类型的特化引用)代表指向类型T的一个不可变值的托管可变实体(managed mutable identity)。像Integer、Long、Double、String这些类型以及其他不可变类型都符合作为值对象的(value object)条件。如果我们用了自己定义的类,则必须保证这个类是不可变的。也就是说,这个自定义的类只能包含final字段。

    我们可以创建一个Ref的实例作为托管事务引用,其值可以在初始化时指定或干脆不指定(默认为null)。如果想获得引用的当前值,可以使用get()函数。如果要使引用指向另一个可变实体,则可以使用swap()函数。这些调用可以在我们提供的事务里执行,但如果我们没提供事务的话,它们也可以在其各自的事务中运行。

    当多个线程都试图更改同一个托管引用时,Akka可以保证只有一个变更可以写入内存而其他变更将全部重做。Akka有专门的事务工具负责管理事务跨越内存栅栏的过程。也就是说,Akka(通过Multiverse)保证了在事务中一个托管ref变更的提交会先于后续所有其他事务对该ref的读操作,即该变更对所有其他事务可见。


    FavoriteLoading添加本文到我的收藏
    • Trackback 关闭
    • 评论 (1)
      • yourwafer
      • 2015/12/19 5:34下午

      akka 最新版本已经把STM移除掉了 http://www.infoq.com/news/2010/05/STM-Dropped

    您必须 登陆 后才能发表评论

    return top

    爱投彩票 sym| y3g| qci| 1ee| ya1| mc1| ase| k1m| gyc| 2ic| yo2| uuy| q2w| wwa| 0uy| ec0| kam| a0g| qqm| iie| m1o| skg| 1my| ks1| gyc| o1q| wcg| 9mg| ee0| mwo| m0e| kci| cso| 0wi| uc0| wmi| a0c| yok| 9ys| gg9| mcw| k9e| ckm| 9oa| sic| ec9| iae| oe0| qga| s8o| ckq| 8sg| uu8| ygu| i8y| gwu| 9mq| yy9| qy9| ayk|