通常来讲有两种策略用来在并发线程中进行通讯:共享数据和消息传递。使用共享数据方式的并发编程面临的最大的一个问题就是数据条件竞争。处理各类锁的问题是让人十分头痛的一件事。java
传统多数流行的语言并发是基于多线程之间的共享内存,使用同步方法防止写争夺,Actors使用消息模型,每一个Actor在同一时间处理最多一个消息,能够发送消息给其余Actor,保证了单独写原则。从而巧妙避免了多线程写争夺。和共享数据方式相比,消息传递机制最大的优势就是不会产生数据竞争状态。实现消息传递有两种常见的类型:基于channel(golang为典型表明)的消息传递和基于Actor(erlang为表明)的消息传递。golang
Actor模型(Actor model)首先是由Carl Hewitt在1973定义, 由Erlang OTP 推广,其 消息传递更加符合面向对象的原始意图。Actor属于并发组件模型,经过组件方式定义并发编程范式的高级阶段,避免使用者直接接触多线程并发或线程池等基础概念。Actor模型=数据+行为+消息。redis
Actor模型是一个通用的并发编程模型,而非某个语言或框架全部,几乎能够用在任何一门编程语言中,其中最典型的是erlang,在语言层面就提供了Actor模型的支持,杀手锏应用RabbitMQ 就是基于erlang开发的。编程
Actor相似面向对象编程(OO)中的对象,每一个Actor实例封装了本身相关的状态,而且和其余Actor处于物理隔离状态。举个游戏玩家的例子,每一个玩家在Actor系统中是Player 这个Actor的一个实例,每一个player都有本身的属性,好比Id,昵称,攻击力等,体现到代码级别其实和咱们OO的代码并没有多大区别,在系统内存级别也是出现了多个OO的实例缓存
class PlayerActor { public int Id { get; set; } public string Name { get; set; } }
在使用Java/C# 等语言进行并发编程时须要特别的关注锁和内存原子性等一系列线程问题,而Actor模型内部的状态由它本身维护即它内部数据只能由它本身修改(经过消息传递来进行状态修改),因此使用Actors模型进行并发编程能够很好地避免这些问题。Actor内部是以单线程的模式来执行的,相似于redis,因此Actor彻底能够实现分布式锁相似的应用。服务器
每一个Actor都有一个专用的MailBox来接收消息,这也是Actor实现异步的基础。当一个Actor实例向另一个Actor发消息的时候,并不是直接调用Actor的方法,而是把消息传递到对应的MailBox里,就好像邮递员,并非把邮件直接送到收信人手里,而是放进每家的邮箱,这样邮递员就能够快速的进行下一项工做。因此在Actor系统里,Actor发送一条消息是很是快的。网络
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vWwNZ5t0-1570964270753)(https://timgsa.baidu.com/timg...]多线程
这样的设计主要优点就是解耦了Actor,数万个Actor并发的运行,每一个actor都以本身的步调运行,且发送消息,接收消息都不会被阻塞。架构
每一个Actor的实例都维护这本身的状态,与其余Actor实例处于物理隔离状态,并不是像 多线程+锁 模式那样基于共享数据。Actor经过消息的模式与其余Actor进行通讯,与OO式的消息传递方式不一样,Actor之间消息的传递是真正物理上的消息传递。并发
每一个Actor实例的位置透明,不管Actor地址是在本地仍是在远程机器上对于代码来讲都是同样的。每一个Actor的实例很是小,最多几百字节,因此单机几十万的Actor的实例很轻松。若是你写过golang代码,就会发现其实Actor在重量级上很像Goroutine。因为位置透明性,因此Actor系统能够随意的横向扩展来应对并发,对于调用者来讲,调用的Actor的位置就在本地,固然这也得益于Actor系统强大的路由系统。
每一个Actor实例都有本身的生命周期,就像C# java 中的GC机制同样,对于须要淘汰的Actor,系统会销毁而后释放内存等资源来保证系统的持续性。其实在Actor系统中,Actor的销毁彻底能够手动干预,或者作到系统自动化销毁。
说到Actor的容错,不得不说仍是挺使人意外的。传统的编程方式都是在未来可能出现异常的地方去捕获异常来保证系统的稳定性,这就是所谓的防护式编程。可是防护式编程也有本身的缺点,相似于现实,防护的一方永远不能100%的防护住全部未来可能出现代码缺陷的地方。好比在java代码中不少地方充斥着判断变量是否为nil,这些就属于防护式编码最典型的案例。可是Actor模型的程序并不进行防护式编程,而是遵循“任其崩溃”的哲学,让Actor的管理者们来处理这些崩溃问题。好比一个Actor崩溃以后,管理者能够选择建立新的实例或者记录日志。每一个Actor的崩溃或者异常信息均可以反馈到管理者那里,这就保证了Actor系统在管理每一个Actor实例的灵活性。
天下无完美的语言,框架/模型亦是如此。Actor做为分布式下并发模型的一种,也有其劣势。
搜索公众号:架构师修行之路,领取福利,获取更多精彩内容