【问题标题】:How does Actors work compared to threads?与线程相比,Actor 如何工作?
【发布时间】:2011-04-04 17:33:27
【问题描述】:

与线程相比,Actor 的工作原理有什么好的简短的解释吗?

一个线程不能被视为一个演员并向其他线程发送消息吗?我看到了一些差异,但对我来说并不是那么清楚。我可以在任何语言中通过不同地使用线程来使用 Actors 吗?

【问题讨论】:

    标签: multithreading concurrency actor message-passing


    【解决方案1】:

    actor 模型对消息传递进行操作。允许各个进程(参与者)彼此异步发送消息。这与我们通常认为的线程模型的区别在于(至少在理论上)没有共享状态。如果有人相信(我认为这是有道理的)共享状态是万恶之源,那么 Actor 模型就会变得非常有吸引力。

    不过,我们不应该过度兴奋。演员模型并没有(与某些指控相反)使死锁成为不可能。 Actor 模型也不会阻止您在不同进程(例如消息队列)之间争用资源。该模型仅在一定级别以上“无锁”。在较低级别,为了协调消息队列,仍然需要锁定。

    不能将线程视为参与者并向其他线程发送消息吗?

    嗯,是的,也不是。不,如果您只是使用在共享内存位置周围放置互斥锁的方法。然后线程共享这个状态——他们都可以访问这个内存,都可以读取它,重写它等等。但是你可以在线程模型之上构建一个actor模型,实际上所有actor实现都有线程下。我通过给每个线程一个由互斥锁保护的队列来组合这样的东西(非常糟糕)——只是为了好玩。要了解如何管理actor-thread 阻抗,请参阅my question from a year ago

    我可以通过不同的线程来使用任何语言的 Actor 模型吗?

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

    您可能还想看看软件事务内存,它是一种不同但也引人注目的模型。 Clojure 是我最喜欢的例子。

    【讨论】:

    • 我越多地使用基于异步消息传递的并发模型(例如 actor 或 async/await),我就越认为它们只是旧的标准同步阻塞并发模型的双重性。异步消息传递并不比使用锁和监视器更容易或更难。事实上,没有共享的可变状态,但只有在单个参与者级别。但是一个 Actor 仍然具有可变状态,并且它实际上可以被所有与之合作的 Actor 观察到。因此,您可能会遇到所有相同的问题:死锁、活锁、饥饿、竞争条件等。
    【解决方案2】:

    我不会说演员总是异步传递消息——那太慢了。举个例子,JActor 项目使用 2 路消息(请求/响应)来更好地为方法调用建模。而且大多数请求都是同步处理的。

    JActor(Java 库)也不使用锁。只有一些原子数据结构和并发数据结构,以及一些信号量。消息传递大约是每秒 80 亿条消息。

    https://github.com/laforge49/JActor

    【讨论】:

    • actor模型仅使用异步通信定义(en.wikipedia.org/wiki/Actor_model)。如果 JActor 不这样做,那么它不仅仅是 100% 的演员模型。它可以简单地使用actor模型作为其众多功能之一。
    猜你喜欢
    • 2013-03-11
    • 2021-07-02
    • 2012-02-28
    • 1970-01-01
    • 2017-07-12
    • 2015-04-08
    • 2013-07-21
    • 2013-10-09
    • 2011-06-01
    相关资源
    最近更新 更多