演员模型与线程相比如何工作?

92

相对于线程,有没有简明扼要的解释如何运用Actor

线程不能被视为一个演员并且发送消息给其他线程吗?我看到了一些差异,但我还不太清楚。通过不同地使用线程,我能在任何编程语言中使用Actor吗?

2个回答

80

Actor模型基于消息传递。单个进程(actors)可以异步地向彼此发送消息。与我们通常所认为的线程模型不同之处在于,理论上不存在共享状态。如果认为共享状态是万恶之源(我认为这是有道理的),那么Actor模型就非常吸引人。

然而,我们不应该过度激动。与某些指控相反,Actor模型并不能使死锁成为不可能。Actor模型也无法防止不同进程之间争夺资源,比如说消息队列。该模型只在某种程度上是“无锁”的。在更低层次上,为了协调消息队列,仍需使用锁。

一个线程能否被视为actor并向其他线程发送消息?

嗯,是和不是。如果您只是采用在共享内存位置周围放置互斥量的方法,则不是。然后线程共享这个状态——它们都可以访问此内存,都可以读取它、重写它等等。但是您可以在线程模型之上构建Actor模型,事实上所有Actor实现都有底层线程。我曾尝试过通过给每个线程分配由互斥量保护的队列来实现这一点(非常糟糕)——只是为了好玩。要了解如何管理Actor-线程阻抗,请参见我去年的问题

能否通过不同地使用线程在任何语言中使用Actor模型?

可以,但需要更多工作。您喜欢的语言很可能有一个消息传递库,所以这将是第一件要调查的事情。此外,您应该研究使用不可变数据结构的方法。请注意,如果数据结构是不可变的,那么您已经基本上解决了“共享状态”问题——多个线程可以持有对不可变数据的引用而不会发生任何不好的事情。这就是为什么Actor语言往往也是函数式语言(erlang、scala)的原因。

你可能还想了解一下软件事务内存(Software Transactional Memory),它是一种不同但同样引人注目的模型。Clojure是我最喜欢的例子。


3
我越来越认为基于异步消息传递的并发模型(例如actors或async/await)只是旧的标准同步阻塞并发模型的对偶。使用异步消息传递与使用锁和监视器相比,实际上并没有更加容易或更加困难。确实,在单个actor级别上并不存在共享的可变状态。但是,一个actor仍然具有可变状态,并且它实际上可以被与之协作的所有其他actors观察到。因此,您可能会遇到所有相同的问题:死锁、活锁、饥饿、竞态条件等等。 - Piotr Kołaczkowski

2

我不会说演员总是异步传递消息——这会太慢了。以JActor项目为例,它使用双向消息(请求/响应)来更好地模拟方法调用。并且大多数请求都是同步服务的。

JActor(一个Java库)也不使用锁。仅使用一些原子和并发数据结构,还有一些信号量。消息传递速度为每秒约80亿条消息。

https://github.com/laforge49/JActor


3
演员模型仅通过使用异步通信来定义(http://en.wikipedia.org/wiki/Actor_model)。如果 JActor 不这样做,那么它就不是完全的演员模型。它可能只是将演员模型作为其众多特性之一。 - B T

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接