使用类型安全平台(包括scala和akka在内)的一个目的是,它能使编写并发软件变得简单。本章主要介绍类型安全平台,特别是akka,是如何在并发应用中处理共享内存的。
java内存模型JMM
在jdk 5之前的版本中,java内存模型的定义并不是很好。当多线程访问共享内存时,可能会得到各种千奇百怪的结果,比如:
看见性问题:一个线程看不到另一个线程写入的值。
指令重排序问题:一个线程可能看到另一个线程完全不可能的行为。因为有些机器指令并不是按照你所以期望的顺序执行。
在java 5之后,很多这样的问题都得到了解决。JMM的规则是基于“happens-before”关系的。这个关系限制了什么时候一个内存访问发生在另一个之前,反过来,也限制了何时允许不按顺序访问。下面是这些规则中的两个例子:
1.监视器锁规则:在其他线程能获取相同的锁之前,这个锁必须先被释放。
2.volatile变量规则:在同时对同一个volatile变量进行读写访问时,写访问必须优先于读访问。
JMM看起来比较复杂,但是它的主要思想是想再使用方便和编写高性能、可扩展的并发数据结构之间寻找一个平衡点。
Actor和JMM
针对akka中actor的实现,多线程有两种方法使用到共享内存:
1.如果一个消息从一个actor发送到另一个actor,在大多数情况下,消息读都是不可变的,但是如果消息不适合构造为不可变对象,如果没有“happen-before”规则,那么接收到的消息对象可能是没有构造完全的对象,甚至根本看不到消息的值。
2.如果处理一条消息时改变了actor的内部状态,稍后处理的另一条消息可能需要访问这个状态。因此必须注意:在actor模型中,你不能保证同一个线程会处理统一个actor的不同消息。
为了防止actor中的可见性问题和重排序问题,akka确保了下面“happen-before”规则:
1.actor发送规则:对同一个actor,发送消息先于接收消息。
2.actor消息顺序处理规则:在同一个actor中,上一条消息的处理先于下一条消息的处理。
注意:一般说来,上一条消息导致的actor内部字段的变化,对于actor处理的下一条消息来说是可见的,因此不需要把actor的字段声明为volatile或者等效(equaivalent)的。另外,上面的两天规则是针对同一个actor来说的,对不同的actor无效。
Futures 和JMM
任何注册在future上回调必须在Future完成之后执行。建议不要过多使用非常量字段,如果你一定要选择非常量字段,你必须使用volatile,以便字段的当前值能对回调可见。如果你过多使用引用,你必须确保这些引用的实例时线程安全的。强烈建议不要使用带锁的对象,以防引入性能问题甚至死锁。
STM和JMM
akka的软件事务内存(STM)也同样支持“happen-before”规则:
STM规则:在事务引用中,一个提交成功的写操作必须在所有的读操作之前。
这个规则有点像JMM中volatile变量,不过当前akkaSTM仅支持延迟写操作,因此实现上共享内存的写操作被延迟到事务提交的时候。事务期间的写数据放在本地buffer中(事务写集合),这个buffer对其他事务不可见。这也保证了不会发生脏读现象。
这些规则的实现细节可能随着版本的不同而改变,甚至具体的细节还可能依赖于配置。但是他们会建造向监视器锁和volatile变量规则一样的其他规则。这意味着akka的使用者不必担心需要自己增加同步模块来支持“happen-before”关系,这是akka负责的工作。你仅仅需要把精力放在你的业务逻辑上,akka框架保证这些规则跟你预期的一模一样。
actor和共享可变状态
毕竟akka是运行在JVM上的,所以还是要遵守一些规则的。下面这个例子是使用actor内部状态,并暴露给其他线程:
class MyActor extends Actor { var state = ... def receive = { case _ => //错误 // 相当的糟糕,共享可变状态 // 会使你的应用出现奇怪的行为 Future { state = NewState } anotherActor ? message onSuccess { r => state = r } // 相当糟糕,“sender”会因为每条消息而改变 // 共享可变状态BUG Future { expensiveCalculation(sender()) } //正确 // 完全安全,“self”可以封装 // and it's an ActorRef, which is thread-safe Future { expensiveCalculation() } onComplete { f => self ! f.value.get } // 完全安全,我们封装一个固定值 // 而且它是一个ActorRef,这个对象是线程安全的 val currentSender = sender() Future { expensiveCalculation(currentSender) } } }
消息必须是不可变的,这样可以避免共享可变状态的陷阱。
相关推荐
Akka 是一个强大的工具包和框架,主要用于构建高度并发、分布式和反应式的应用程序,它基于actor模型。在Java中,Akka可以用来实现TCP远程调用,这使得不同系统之间能够通过网络进行通信。下面我们将深入探讨如何...
Akka 的设计考虑到了 Java 内存模型的影响,确保了 Actor 的线程安全性和内存一致性。 ##### 2.8 Message Delivery Reliability Akka 支持可靠的消息传递机制,确保消息不会丢失或重复发送。 ##### 2.9 ...
Akka 的设计考虑到了 Java 内存模型的影响,确保了 Actor 在并发环境下的正确行为。 ##### 2.8 消息传递的可靠性 Akka 保证了消息传递的可靠性。如果 Actor 无法处理消息,Akka 会根据配置采取相应的措施,如重试...
AkkaJava PDF Doc涉及了关于Akka actor模型的广泛主题,从基础概念到高级特性,再到实际应用中的模式和工具。文档强调了在低版本Java环境下如何使用Akka进行高效的并发编程,并且通过具体的API介绍,帮助开发者理解...
Java的Akka学习入门文档是...总之,Java的Akka学习入门文档将引导你走进Actor模型的世界,让你掌握构建高效、可靠的分布式系统的技巧。通过深入阅读和实践,你将能够利用Akka的力量来解决复杂的并发和分布计算问题。
由于Akka是基于Java平台构建的,因此文档还将讨论Akka如何处理Java内存模型和消息传递保证。 在 Actors 章节中,文档将深入探讨Akka中的Actors和TypedActors,以及它们如何实现故障转移、调度器、邮箱、路由、构建...
Akka 是一个强大的开源工具,主要用于构建高度并发、分布式和反应式的应用程序,主要在Java和Scala语言环境下使用。它的核心设计理念是Actor模型,这使得它能够处理大量的并发操作,同时保持系统的可扩展性和容错性...
- **Akka 与 Java 内存模型的关系:** Akka 通过设计确保 Actor 之间的消息传递符合 Java 内存模型的规定。 **2.8 消息传递可靠性** - **可靠消息传递:** 介绍 Akka 如何保证消息不会丢失。 - **消息重传机制:** ...
在解决这些难点时,理解AKKA-HTTP的路由系统、WebSocket处理、SSL/TLS配置、以及Akka Actor模型的关键概念至关重要。同时,对于复杂的HTTP和WebSocket应用,良好的错误处理和监控也是必不可少的。AKKA-HTTP提供了...
We believe that writing correct ...Please note that all code samples compile, so if you want direct access to the sources, have a look over at the Akka Docs subproject on github: for Java and Scala.
- **定义**:Akka 是一个用于构建高度并发、分布式、容错性应用的工具包,适用于 Java 和 Scala 开发者。它基于 Actor 模型,支持响应式编程范式。 - **目标**:Akka 的主要目标是简化并发编程,使得开发者能够轻松...
- 讲述了Akka和Java内存模型的关系,以及消息传递的可靠性。 - 介绍了Akka的监督、监控、故障容错、类型化Actor、调度器、消息箱、路由、有限状态机Actor构建、持久化以及测试Actor系统的相关知识。 - 详述了如何...
#spring-boot-akka-java 一个使用 Java 8 的涉及 Spring Boot 和 Akka 的 Web 应用程序 前言 作为初学者,我发现将 Akka 与 Spring 的依赖注入集成有点复杂,尤其是在我使用 Java 时。 这个应用程序是向前迈出的一步...
Java 协程实现Akka是将传统的线程模型与轻量级、低开销的并发机制相结合的一种方式。Akka是用Scala编写的,但在Java中也可以方便地使用,它提供了一个强大的actor模型来处理并发问题,使得在高度并行和分布式系统中...
第 1 章 初识 Actor:Akka 工具集以及 Actor 模型的介绍。 第 2 章 Actor 与并发:响应式编程。Actor 与 Future 的使用。 第 3 章 传递消息:消息传递模式。 第 4 章 Actor 的生命周期—处理状态与错误:Actor 生命...
Akka is a toolkit and runtime for building highly concurrent, distributed, and resilient message-driven applications on the JVM.
Akka框架借鉴了Erlang的并发模型,但它是建立在JVM之上,并且提供了丰富的抽象和工具,能够简化开发工作。 标题“Akka Scala 学习高清原版pdf”表明该文档是一个专注于Scala语言在Akka框架中应用的指南,而“描述”...
Akka是一个基于Actor模型的高性能、高并发框架,主要应用于Scala和Java平台。由Lightbend公司(前身为Typesafe)开发,它提供了构建分布式系统和容错应用程序的强大工具。Akka的核心设计理念是通过Actor模型来简化多...