“并发是一种解耦策略” —— Robert C.Martin
何为Actor模式呢?
引用维基百科的解释 Actor Model
在计算机科学中,参与者模式(Actor model)是一种并发运算上的模型。“参与者”是一种程序上的抽象概念,被视为并发运算的基本单元:当一个参与者接收到一则消息,它可以做出一些决策、创建更多的参与者、发送更多的消息、决定要如何回答接下来的消息。
这段话很全面,但也需要我们花时间来消化与理解。不妨先试着阅读以下这段Python代码实现,再分析理解。
from queue import Queue
from threading import Thread
class ActorExit(Exception):
pass
class Actor(object):
def __init__(self):
self._thread = Thread()
self._queue = Queue()
def send(self, msg):
self._queue.put(msg)
def receive(self):
msg = self._queue.get()
if msg is ActorExit:
raise ActorExit()
return msg
def stop(self):
if self._thread.is_alive():
self.send(ActorExit)
def start(self):
if not self._thread.is_alive():
self._thread = Thread(target=self._bootstrap)
self._thread.start()
def _bootstrap(self):
try:
self.run()
except ActorExit:
pass
def run(self):
while True:
msg = self.receive()
print(msg)
# Sample Actor
class PrintActor(Actor):
def run(self):
while True:
msg = self.receive()
print("Got:", msg)
if __name__ == '__main__':
p = PrintActor()
p.start()
p.send("Hello")
p.send("World")
p.stop()
这里我们定义了Actor模式的基类Actor
和其子类实现PrintActor
。
Actor
对象是一个计算单元,所以每个actor都需要包含了一个Thread
对象,用以执行给定的消息处理操作。同时actor对象也包含了一个Queue
对象,实现了异步调用(在send消息后能立刻返回控制权)。
在启动actor之后,线程对象会执行引导函数_bootstrap
,进而执行run
函数。一般来说,在run
函数里,我们会通过receive
函数来读取之前通过send函数发送来的消息,然后根据给定的逻辑处理消息。特别地,receive
函数会抛出ActorExit
异常,而ActorExit
异常正是我们作为停止线程的哨兵值。
Actor model 作为一种并发运算模型,其作用在于将 目的(做什么)和时机(何时做)解耦,以优化应用程序的吞吐量和结构。例如用户想要打印一段信息,那么他需要去调用对应的PrintActor
的send函数(目的),然后程序会立刻返回,继续执行操作;至于这个打印的需求何时(时机)用户则无需关心。而这也是Actor模式吸引人之处——简单性:用户设计时,只需在其子类中定义好 run
函数中的处理操作,使用时只需调用send
函数,消息就能得到对应的处理。
抽象到一个新的高度,我们可以看到Actor模式在设计上有3个并发防御原则:
- 单一权责:每个actor只负责处理对应类型的消息,且其中的并发代码和其他组件的代码是分隔开的。
- 限制数据成员作用域:actor只开放
send
接口,最大程度地减小内部成员的暴露,限制可能被共享的数据的访问,缩减“临界区”范围。 - 线程之间独立:每个actor线程都只在自己的世界里存在,不与其他线程共享数据。线程之间唯一的交互是
send
出去的消息,所以,当消息是不可变对象 或者 actor存储的是消息副本时,就能保证两个线程之间是独立的。
妥善使用Actor模式,保证子类也符合这三个原则,那么程序在架构层面上,能很好地降低多线程应用程序设计的复杂度。
最后,我们发散一下思维。
这里PrintActor是最简单的一种Actor,实践中我们可以设计一个DatabaseActor,用来存储数据;设计一个LogActor,用来记录日志;甚至可以把send方法实现为在socket上的数据传输,将“发送信息”这一概念扩展到多进程甚至是分布式系统之中。
参考书籍:
- 《Python Cookbook》第三版
- 《代码整洁之道》Robert C.Martin
网友评论