Akka简化了编写并发软件的过程,本文主要讨论Akka如何在并发应用中访问共享内存。
Java内存模型
Java5之前的JMM是相当混乱的。多线程访问共享内存很有可能会得奇怪的结果,如:
- 可见性问题,无法及时看到其他线程写入的值
- 指令乱序,观测到其他线程不可能的行为
从Java 5的JSR 133的实现,很多问题就解决了。JMM是基于一组"happens-before"关联规则,限制了访问内存的行为必须在另一个内存访问行为之前发生。当不想按顺序发生时,可以使用:
- 监视器锁规则:对一个锁的释放先于所有后续对同一个锁的获取
- volatile变量规则:对一个volatile变量的写操作先于所有后续对同一个volatile变量的读
JMM看起来很复杂,但是其规范试图在编写高性能,并发数据结构的能力间寻找平衡
Actor与Java内存模型
使用Akka的Actor,有两种方法可以使多线程操作共享内存:
- 假如一个message被发送给一个actor,在大多数情况下,message是不可变对象,万一message不是不可变的,没有”happen before"规则,receiver可能会看到部分初始化的数据,甚至可能看到无中生有的数据(long/double)
- 如果一个actor在处理消息时,改变了自己的内部状态,而后又在处理其他消息的时候访问了这个状态。我们需要知道的是,在使用Actor模型时,无法保证同一个线程在处理不同消息时,使用同一个actor(是指一个线程中有多个actor?还是一个actor改变了自己内部的状态后,就不是同一个actor?)
为了防止actor出现可见性问题,执行顺序问题,Akka制定了如下"happen before"规则:
- 发送规则:一条消息的发送动作先于同一个actor对同一条消息的接收
- actor后续处理规则:一条消息的处理,优先于同一个actor的下一条消息
两条规则只对同一个actor实例有效
通俗的解释:actor的内部变量(internal fields)是可见的,当下一个消息准备被处理时。所以你的actor的内部变量必须是volatile或者equivalent。
Futures与Java内存模型
一个Future的完成 “先于” 任何注册到它的回调函数的执行。
我们建议不要捕捉(close over)非final的值 (Java中称final,Scala中称val), 如果你 一定 要捕捉非final的值, 它们必须被标记为 volatile 来让它的当前值对回调代码可见。
如果你捕捉一个引用,, 你还必须保证它所指代的实例是线程安全的。 我们强烈建议远离使用锁的对象,因为它们会引入性能问题,甚至可能造成死锁。 这些是使用synchronized的风险。
STM与Java内存模型
Akka中的软件事务性内存 (STM) 也提供了一条 “发生在先” 规则:
- 事务性引用规则: 在提交过程中对一个事务性引用的成功的写操作先于所有对同一事务性引用的后续读操作发生。
这条规则非常象JMM中的 ‘volatile 变量’ 规则. 目前Akka STM只支持延迟写,所以对共享内存的实际写操作会被延迟到事务提交之时。事务中的写操作被存放在一个本地缓冲区中 (事务的写操作集) ,对其它的事务是不可见的。这就是为什么脏读是不可能的。
这些规则在Akka中的实现会随时间而变化,精确的细节甚至可能依赖于所使用的配置。但是它们是建立在其它的JMM规则如监视器锁规则和volatile变量规则基础上的。 这意味着Akka用户不需要操心为了提供“发生先于”关系而增加同步,因为这是Akka的工作。这样你可以腾出手来处理你的业务逻辑,让Akka框架来保证这些规则的满足。
Actors与共享的可变状态
由于Akka运行在JVM,有些规则仍然必须遵守
-
捕捉actor内部状态并暴露给其他线程
class MyActor extends Actor { var state = ... def receive = { case _ => //错误示范 // Very bad, 共享可变状态, // will break your application in weird ways Future { state = NewState } anotherActor ? message onSuccess { r => state = r } // Very bad, "sender" 随每个消息改变, //共享可变状态 bug Future { expensiveCalculation(sender()) } //正确示范 // Completely safe, "self" is OK to close over // and it's an ActorRef, which is thread-safe Future { expensiveCalculation() } onComplete { f => self ! f.value.get } // 非常安全,我们捕捉了一个固定值 // 并且它是一个Actor引用,是线程安全的 val currentSender = sender() Future { expensiveCalculation(currentSender) } } }
- 消息应该是不可变的,为了避免共享可变状态的陷阱
http://blog.csdn.net/wsscy2004/article/details/38421313
相关推荐
在"scala学习笔记整理"中,我们可以深入探讨以下关键知识点: 1. **基础语法**:Scala的基础语法与Java有相似之处,但也有很多独特的特点。例如,它支持变量的不可变性(immutability),使用`val`声明常量,`var`...
首先,我们来看"ConcurrentProgrammingStudyNotes",这可能是一份关于Java并发编程的学习笔记。并发编程涉及线程管理、同步机制、锁、并发容器、并发工具类等内容。Java提供了丰富的API来支持并发,如`java.util....
5. Akka框架:Akka是用Scala编写的开源框架,用于构建高度可扩展、容错的应用程序,它充分利用了Scala的Actor模型。 6. Scala与Java互操作:由于Scala是运行在JVM上的,所以可以直接使用Java库,与Java代码无缝集成...
- Scala与其他技术的结合:如Spark、Akka等,学习如何在实际项目中应用Scala。 总的来说,Scala是一种强大的工具,它的设计哲学是提供一种既能充分利用面向对象编程的优势,又能发挥函数式编程优点的语言。通过学习...
分析如`Akka`、`Quasar`或`Disruptor`等并发框架的源码,可以深入理解如何在Java中构建高效的并发系统,学习其设计思想和最佳实践。 通过阅读和研究这些源码,开发者不仅可以提升对Java并发编程的理解,还能学习到...
7. 响应式编程:Scala与Akka框架结合,支持响应式编程模型。 四、模式匹配 8. 模式匹配:用于处理数据结构,如case class和枚举。例如: ```scala sealed trait Color case object Red extends Color case object ...
本教程“scala-learn:scala学习笔记”旨在帮助初学者深入理解Scala的基础知识,同时也为有经验的程序员提供了一个复习和提升的平台。 1. **基础语法与数据类型** Scala的基础语法简洁而强大,包括变量声明(val和...
这部分可能包括如何使用Scala进行数据处理、如何利用Scala与其他Java库集成、以及如何编写测试和调试Scala代码的策略。此外,还可能涵盖了一些常见的编程陷阱和避免它们的方法。 通过这些PDF文档的学习,你将不仅...
9. ** Akka框架**:Akka是基于Actor模型的并发处理库,通常与Scala一起用于构建高可用、容错的系统。 10. ** Spark与Scala结合**:讲解如何使用Scala来编写Spark应用程序,包括DataFrame、RDD和Spark SQL等关键组件...
### Spark源码解析:Master与Worker机制 #### Spark概述及特点 Spark是一个高效的数据处理框架,它由加州大学伯克利分校的AMP实验室研发。该框架支持多种编程语言(包括Java、Scala、Python和R等),使开发者可以...
3. **Scala与Java及JVM的关系**: Scala是基于JVM的,这意味着Scala编译后的代码可以被JVM执行。这为Scala提供了广泛兼容Java库的能力,同时也意味着开发者可以利用已有的Java基础设施。然而,Scala的语法和特性比...
6. ** Actors 和 Akka**:Scala广泛用于构建并发和分布式系统,Actors模型提供了一种管理并发的方式,Akka则是基于Actors的开源框架,用于构建可扩展的、容错的系统。 7. **Scala REPL**:Scala交互式解释器(Read-...
Scala是一种强大的编程语言,运行在Java虚拟机(JVM)上,它将现代的面向对象编程模型、函数式编程和高级类型系统的优势融为一体。《Scala程序设计(第2版)》这本书详细介绍了Scala编程语言,并通过大量的代码示例...
Akka框架,基于Scala的Actor库,提供了一种高效、容错的并发编程模型。通过Actor,程序中的组件可以并行执行,且通过消息传递进行通信,避免了共享状态的问题,从而简化了并发编程的复杂性。 另外,Scala还与Java...
Scala的Akka库提供了Actor模型,这是一种用于处理并发和分布式系统的强大工具。Actors是轻量级的线程,通过消息传递进行通信,保证了系统的一致性。 **8. Scaladoc** Scala的文档生成工具Scaladoc与Java的Javadoc...
"scala-notes"可能是一个关于Scala编程的学习笔记或者教程集合,而"scala-notes-master"可能代表这是该资料的主目录或者最新版本。 在Scala中,你将学习到以下关键概念: 1. **类型系统**:Scala有强大的静态类型...