Reactor,Proactor,Actor_reactor actor-CSDN博客
Actor模型是一种并发编程模型,它定义了计算单元的行为,这些计算单元被称为Actors。Actors通过消息传递进行通信,它们之间相互隔离,不共享内存。Actors模型的核心概念包括:
消息传递:Actors通过接收和发送消息来执行计算和通信。消息传递是Actors之间唯一的交互方式,这使得Actors具有高度的解耦性和并行性。
状态管理:Actors管理自己的状态,这些状态由Actors自己维护,避免了在并发环境下使用锁和内存原子性操作的问题。
异步性:Actors是异步的,它们不等待消息被接收,而是继续执行其他操作。这种异步性使得Actors能够并发执行,而不需要同步机制。
并发实体:Actors可以被视为应用级别的线程,它们在用户空间实现,不共享操作系统级别的资源,如锁和内存。
事件驱动:Actors的事件处理依赖于线程(队列、池),但它们本身是独立的,不会因为线程的调度而阻塞。
Actors模型在不同的编程语言中有不同的实现,例如在Erlang中,Actors通过OTP(Erlang OTP)得到广泛应用。在Java中,Akka是一个实现Actors模型的框架。Actors模型的应用场景包括但不限于分布式计算、消息队列和微服务架构。
总结来说,Actors模型是一种基于消息传递的并发编程模型,它强调异步性、并发实体和事件驱动,适用于需要高度解耦和并行的计算场景。12
浅析并发编程模型——Actor模型 (qq.com)
Actor模型的基础就是消息传递,一个Actor模型可以认为是一个基本的计算单元,它能接收消息并基于消息执行运算,也可以发送消息给其他Actor模型。各个Actor模型之间相互隔离,不共享内存。
Actor模型本身封装了状态和行为,在进行并发编程时,Actor模型只需要关注消息和其本身。而消息是一个不可变对象,所以Actor模型不需要去关注锁和内存原子性等一系列多线程常见的问题。
Actor模型由状态(State)、行为(Behavior)和邮箱(MailBox,可以认为是一个消息队列)三部分组成:
2.1 Reactor:
主动模式。所谓主动,是指应用程序不断轮询,询问操作系统或者网络框架,IO是否就绪。Linux系统下的select、poll和epoll属于主动模式,需要应用程序中有一个循环一直轮询;Java中的NIO也属于这种模式。在这种模式下,实际的IO操作还是应用程序执行的。
流程:
1 向事件分发器注册事件回调
2 事件发生
4 事件分发器调用之前注册的函数
4 在回调函数中读取数据,对数据进行后续处理
Reactor模型实例:libevent,Redis、ACE
2.2 Proactor:
被动模式。应用程序把read和write函数操作全部交给操作系统或者网络框架,实际的IO操作由操作系统或网络框架完成后,之后再回调应用程序。asio库就是典型的Proactor模式。
异步IO就是Proactor模式。
流程:
1 向事件分发器注册事件回调
2 事件发生
3 操作系统读取数据,并放入应用缓冲区,然后通知事件分发器
4 事件分发器调用之前注册的函数
5 在回调函数中对数据进行后续处理
Preactor模型实例:ASIO
2.3 Reactor和Proactor的主要区别:
reactor和proactor的主要区别是,前者应用在回调函数中读取数据,然后进行后续的数据处理;而后者数据读取有操作系统完成,回调函数制作数据处理。Proactor是异步,Reactor是同步阻塞。
主动和被动
以主动写为例:
Reactor将handle放到select(),等待可写就绪,然后调用write()写入数据;写完处理后续逻辑;
Proactor调用aoi_write后立刻返回,由内核负责写操作,写完后调用相应的回调函数处理后续逻辑;
可以看出,Reactor被动的等待指示事件的到来并做出反应;它有一个等待的过程,做什么都要先放入到监听事件集合中等待handler可用时再进行操作;
Proactor直接调用异步读写操作,调用完后立刻返回;
实现
Reactor实现了一个被动的事件分离和分发模型,服务等待请求事件的到来,再通过不受间断的同步处理事件,从而做出反应;
Proactor实现了一个主动的事件分离和分发模型;这种设计允许多个任务并发的执行,从而提高吞吐量;并可执行耗时长的任务(各个任务间互不影响)
优点
Reactor实现相对简单,对于耗时短的处理场景处理高效;
操作系统可以在多个事件源上等待,并且避免了多线程编程相关的性能开销和编程复杂性;
事件的串行化对应用是透明的,可以顺序的同步执行而不需要加锁;
事务分离:将与应用无关的多路分解和分配机制和与应用相关的回调函数分离开来,
Proactor性能更高,能够处理耗时长的并发场景;
缺点
Reactor处理耗时长的操作会造成事件分发的阻塞,影响到后续事件的处理;
Proactor实现逻辑复杂;依赖操作系统对异步的支持,目前实现了纯异步操作的操作系统少,实现优秀的如windows IOCP,但由于其windows系统用于服务器的局限性,目前应用范围较小;而Unix/Linux系统对纯异步的支持有限,应用事件驱动的主流还是通过select/epoll来实现;
适用场景
Reactor:同时接收多个服务请求,并且依次同步的处理它们的事件驱动程序;
Proactor:异步接收和同时处理多个服务请求的事件驱动程序;
2.4 Actor:
Actor模型被称为高并发事务的终极解决方案,
实体之通过消息通讯,各自处理自己的数据,能够实现这并行。
actor模型实例:skynet,Erlang
Actor模型是一个概念模型,用于处理并发计算。它定义了一系列系统组件应该如何动作和交互的通用规则,最著名的使用这套规则的编程语言是Erlang。
一个Actor指的是一个最基本的计算单元。它能接收一个消息并且基于其执行计算。
这个理念很像面向对象语言,一个对象接收一条消息(方法调用),然后根据接收的消息做事(调用了哪个方法)。
Actors一大重要特征在于actors之间相互隔离,它们并不互相共享内存。这点区别于上述的对象。也就是说,一个actor能维持一个私有的状态,并且这个状态不可能被另一个actor所改变。
思路方向:
其实无论是使用数据库锁 还是多线程,这里有一个共同思路,就是将数据喂给线程,就如同计算机是一套加工流水线,数据作为原材料投入这个流水线的开始,流水线出来后就是成品,这套模式的前提是数据是被动的,自身不复杂,没有自身业务逻辑要求。适合大数据处理或互联网网站应用等等。
但是如果数据自身要求有严格的一致性,也就是事务机制,数据就不能被动被加工,要让数据自己有行为能力保护实现自己的一致性,就像孩子小的时候可以任由爸妈怎么照顾关心都可以,但是如果孩子长大有自己的思想和要求,他就可能不喜欢被爸妈照顾,他要求自己通过行动实现自己的要求。
数据也是如此。
只有我们改变思路,让数据自己有行为维护自己的一致性,才能真正安全实现真正的事务。
我们可以看到
Actor模型=数据+行为+消息。
Actor模型内部的状态由自己的行为维护,外部线程不能直接调用对象的行为,必须通过消息才能激发行为,这样就保证Actor内部数据只有被自己修改。