《虚拟机并发编程》读书笔记(二)关于STM

原创
2013/07/08 19:54
阅读数 638

这部分内容讲述了软件事务内存,这部分对大部分程序员来说可能是个比较陌生的领域。这是Clojure中很流行的一种并发编程模型。当然这并不是去多学一门语言,而是不同的语言设计都有他各自的特点,很多设计模式都是可以借鉴的,通俗的讲就是给编程更开阔的视野。

并发程序出问题的都是那些可变的状态,对于那些你定义成final的变量,这种不可变的状态确保了在并发执行过程中的一致性。而实现ClojureSTM模型中一个关键的步骤就是将状态与实体分离。也就是说,状态与实体的改变将互不影响(当然了实体和状态是有关联的),状态的改变将不再影响到实体的一致性。状态与实体分离有助于STM解决和同步有关的两大问题:跨越内存栅栏和避免竞争条件。

Clojure中,STM这样来反映,在设计上值是不可变的,而实体也只能在事务中才能改变。并且不提供改变状态的方法,如果在事务之外改变状态,那么马上抛出异常。这种做法其实从编译阶段就给了用户很直观的结果,异常直接告诉你这样的方式会造成并发问题,所以程序就不能这么写。这跟java就很大的不同,哪怕你写的程序犯了最低等的共享问题,但是程序照样能跑下去。这点上Clojure确实给并发程序开发者提供了很人性化的提示。

一个简单的例子:

(def balance (ref 0))

(print “Balance is” @balance)

(dosync 
(ref-set blance 100))

(print “Balance now is” @balance)

dosync中执行的改变都是被事务控制的。当然你可能会有疑问,如果都是在事务中进行,那多个事务怎么进行并发,有没有顺序性,谁的结果是正确的。在Clojure中,如果事务发现本地拷贝已经失效,那STM将重做这个事务。在《虚拟机并发编程》中还提高了写偏斜异常的问题,当然给出了Clojure的相关解决方案,这里就不赘述了。

STM适用于读多写少的并发环境。在java中如果你要以STM的方式实现并发有三种方式:

第一种:直接在java中使用Clojure STM,只需将事务代码封装在一个Callable接口的实现中即可。当然需要引用Clojure STM的相关依赖。

第二种:使用MultiverseSTM API

第三种:使用AkkaAkka库是scala开发的一组事务类库。

写了那么多主要是为并发编程提供一种思路,我觉得绝大数人肯定不会愿意花代价去更改原有的代码,而且1.5之后的并发编程门槛确实也降低了不少,但是好的思路和一些新的理念还是值得我们去学习的。


展开阅读全文
打赏
3
5 收藏
分享
加载中
更多评论
打赏
0 评论
5 收藏
3
分享
返回顶部
顶部