Actors编程模型

澳门新葡亰手机版 2

多线程已经成为大多数开发者的兴趣所在了。他们努力尝试想找出最优策略来解决这个问题。过去已经有各种尝试去标准化这些方案。特别是随着大数据,实时分析等问题领域的兴起,又存在着新的挑战。在这个方向需要走的一步是“Doug
Lea”的作品(一部巨作),以并发框架(JSR 166)的形式提供给我们。

  Actors模型(Actor model)首先是由Carl Hewitt在1973定义, 由Erlang OTP
(Open Telecom Platform) 推广,其 消息传递更加符合面向对象的原始意图。
Actors属于并发组件模型
,通过组件方式定义并发编程范式的高级阶段,避免使用者直接接触多线程并发或线程池等基础概念。

现在开始区分并发和并行性。这些只是不同的策略,而且市面上有很多框架提供,都能帮我们达到相同的目的。但在选择的时候如果能同时知道他们内部的实现细节对我们也是大有好处的。本文将要探究JVM线程池和线程共享的一些稳定有效的选项。当然,随着多核处理器的广泛使用,新的问题也随之而来。开发人员也开始思考利用高级硬件的“mechanical
sympathy”(译者注:表示底层硬件的运作方式以及与硬件运行方式协同的软件编程)来提高性能。

  
传统多数流行的语言并发是基于多线程之间的共享内存,使用同步方法防止写争夺,Actors使用消息模型,每个Actors在同一时间处理最多一个消息,可以发送消息给其他Actors,保证了单独写原则 。从而巧妙避免了多线程写争夺。

个人以为,当讨论线程池时,目前广泛应用的主要有下述机制:

   Actors模型的特点是:

  1. Executor框架提供的线程。
  2. LMAX的Ring Buffer概念 (译者注:Ring
    Buffer即环形缓冲,LMAX是一种新型零售金融交易平台,其框架能以低延迟产生大量交易,LMAX建立在JVM平台上。
  3. 基于Actor(事件)的实现。
  • 隔离计算实体
  • “Share nothing”
  • 没有任何地方同步
  • 异步消息传递
  • 不可变的消息 消息模型类似mailbox / queue

并发框架下的线程池选项:

  
AKKA框架是一个实现Actors模型的Scala或Java平台,灵感来自ERlang,能更轻松地开发可扩展,实现多线程安全应用。

首先,我个人不赞同使用当下流行的线程池概念,而应该使用工作队列的概念。简而言之,在一个执行框架可供选择的各种不同选项都是基于某种顺序数据结构,如数组或队列(阻塞或非阻塞)之类的,比如ConcurrentLinkedQueue(并发链式队列),ArrayBlockingQueue(数组阻塞队列),
LinkedBlockingQueue(链式阻塞队列)等等。文档表明,尽管它们的使用环境各不相同,但他们隐含的本质/数据结构有相同的性质,如顺序插入和遍历。

  Actors是一个轻量级的对象,通过发送消息实现交互。每个Actors在同一时间处理最多一个消息,可以发送消息给其他Actors。在同一时间可以于一个Java虚拟机存在数以百万计的参与者,构架是一个分层的父层(管理)

子层,其中父层监控子层的行为。还可以很容易地扩展Actor运行在集群中各个节点之间

  • 无需修改一行代码。每个演员都可以有内部状态(字段/变量)
    ,但通信只能通过消息传递,不会有共享数据结构(计数器,队列)
    。Akka框架支持两种语言Java和Scala,

 

WhatsApp成功背后的Erlang语言

Actor模型和CSP模型的区别

高级并发:Akka Actors和JavaEE7的EJB比较

Akka教程

AKKA框架介绍

使用Akka发送1000万消息

使用Akka实现MapReduce的单词计数

Akka+ZeroMQ消息生产者和消费者

软件事务内存STM

RXJAVA的Observable和AKKA ACTOR综合使用

为什么Actor模型是高并发事务的终极解决方案?

actor并发模型&基于共享内存线程模型

Spray + Akka高性能异步IO并发

使用Scala的Akka HTTP,Akka Stream和Reactive
Mongo建立REST服务

单独写原则

LMAX架构

澳门新葡亰手机版,go reactive宣言

Scala入门之函数编程

Scala入门之基本概念

vertx入门教程

使用Kafka和ZeroMQ实现分布式Quasar Actor

 

澳门新葡亰手机版 1

相关参考

Actors模型更多专题

AKKA更多专题

reactive编程

Scala专题

Disruptor专题

并发编程

性能专题

EDA事件驱动专题

 

 

过去十几年CPU一直遵循着摩尔定律发展,单核频率越来越快,但是最近这几年,摩尔定律已然失效,CPU的工艺制程和发热稳定性之间难以取舍,取而代之的策略则是增加核心数量,目前家用电脑四核已经非常常见,服务器更是达到了32核64线程。为了有效地利用多核CPU,我们在代码层面就应该考虑到并发性。十几年的痛苦开发经历告诉我们,threads并不是获取并发性的好方法,往往会带来难以查找的bug,但是不用害怕,今天我们有很多其他方法来获得易用的并发性,比如我们接下来介绍的Actor模型。

模型 Model

Actor模型是一个概念模型,用于处理并发计算。它定义了一系列系统组件应该如何动作和交互的通用规则,最著名的使用这套规则的编程语言是Erlang。这篇文章更关注模型本身而不是它在不同语言的实现。

Actors

一个Actor指的是一个最基本的计算单元。它能接收一个消息并且基于其执行计算。

这个理念很像面向对象语言,一个对象接收一条消息(方法调用),然后根据接收的消息做事(调用了哪个方法)。

Actors一大重要特征在于actors之间相互隔离,它们并不互相共享内存。这点区别于上述的对象。也就是说,一个actor能维持一个私有的状态,并且这个状态不可能被另一个actor所改变。

聚沙成塔

One ant is no ant, one actor is no actor.
光有一个actor是不够的,多个actors才能组成系统。在actor模型里每个actor都有地址,所以它们才能够相互发送消息。

Actors有邮箱

只得指明的一点是,尽管许多actors同时运行,但是一个actor只能顺序地处理消息。也就是说其它actors发送了三条消息给一个actor,这个actor只能一次处理一条。所以如果你要并行处理3条消息,你需要把这条消息发给3个actors。

消息异步地传送到actor,所以当actor正在处理消息时,新来的消息应该存储到别的地方。Mailbox就是这些消息存储的地方。

 

澳门新葡亰手机版 2

Actors通过异步消息沟通,在处理消息之前消息被存放在Mailbox中

Actors做什么

当一个actor接收到消息后,它能做如下三件事中的一件:

  • Create more actors; 创建其他actors
  • Send messages to other actors; 向其他actors发送消息
  • Designates what to do with the next message.
    指定下一条消息到来的行为

前两件事比较直观,第三件却很有意思。

我之前说过一个actor能维持一个私有状态。「指定下一条消息来到做什么」意味着可以定义下条消息来到时的状态。更清楚地说,就是actors如何修改状态。

设想有一个actor像计算器,它的初始状态是数字0。当这个actor接收到add(1)消息时,它并不改变它原本的状态,而是指定当它接收到下一个消息时,状态会变为1。

容错 Fault tolerance

Erlang
引入了「随它崩溃」的哲学理念,这部分关键代码被监控着,监控者的唯一职责是知道代码崩溃后干什么(如将这个单元代码重置为正常状态),让这种理念成为可能的正是actor模型。

每段代码都运行在process中,process是erlang称呼actor的方式。这个process完全独立,意味着它的状态不会影响其他process。我们有个supervisor,实际上它只是另一个process(所有东西都是actor),当被监控的process挂了,supervisor这个process会被通知并对此进行处理。这就让我们能创建「自愈」系统了。如果一个actor到达异常状态并崩溃,无论如何,supervisor都可以做出反应并尝试把它变成一致状态,这里有很多策略,最常见的是根据初始状态重启actor。

分布式 Distribution

另一个关于actor模型的有趣方面是它并不在意消息发送到的actor是本地的或者是另外节点上的。

转念一想,如果actor只是一些代码,包含了一个mailbox和一个内部状态,actor只对消息做出响应,谁会关注它运行在哪个机器上呢?只要我们能让消息到达就行了。这允许我们基于许多计算机上构建系统,并且恢复其中任何一台。

进一步了解

这里是一个快速的概念模型回顾,其中的概念被运用到许多知名语言和库中,比如Erlang和Elixir,
Akka (for the JVM) 和 Celluloid (for Ruby)。

如果你想更深入了解actor及其背后的原理,你可以进一步阅读下面书籍和文章:

  • Seven Concurrency Models in Seven Weeks: When Threads
    Unravel
  • Programming
    Elixir
  • Elixir in
    Action
  • Actor模型
  • 为什么Actor模型是高并发事务的终极解决方案?

这个视频比较完整地讨论了Actor的概念模型。
The Actor Model (everything you wanted to
know)

Scala或Erlang的进程信箱都是一种Actor模型,也有Java的专门的Actor模型,这里是几种Actor模型比较明白了Actor模型原理,使用Disruptor这样无锁队列也可以自己实现Actor模型,让一个普通对象与外界的交互调用通过Disruptor消息队列实现,比如LMAX架构就是这样实现高频交易,从2009年成功运行至今,被Martin
Fowler推崇。

原文地址:
http://www.brianstorti.com/the-actor-model/

作者:时见疏星
链接:https://www.jianshu.com/p/449850aa8e82
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

 

 

优势:

  1. 减少线程创建导致的延迟
  2. 通过优化线程数量,可以解决资源不足的问题。

这些可以使应用程序和服务器应用响应更快。使用线程池看似一个很不错的解决方案但是却有一个根本性的缺陷:连续争用问题。这里是Java中关于一些并发框架下线程池选项的讨论。

Disruptor(环形缓冲):

(LMAX的一个基于环形缓冲区的高性能进程间消息库)LMAX的开发人员使用一个干扰框架来解决连续争用问题,这个框架是基于一个叫环形缓冲的数据结构。它可能是线程间发送消息的最有效方式了。它是队列的一种替代实现方式,但它又和SEDA和Actors(译者注:这两种都是和Disruptor类似的并发模型)有一些共同特征。向Disruptor中放入消息需要两步,第一步申请一个环形缓冲的槽位,槽位可为用户提供写对应数据的记录。然后需要提交该条记录,为了能灵活使用内存,2步法是必须的。只有经过提交,这条消息才能对消费者线程可见。下图描述了环状缓冲这个数据结构(Disruptor的核心):

(译者注:LMAX的核心是一个业务逻辑处理器,而该业务逻辑处理器的核心是Disruptor,这是一个并发组件,能够在无锁的情况下实现网络的Queue并发操作)