【问题标题】:Actors: How to efficiently handle read-mostly data演员:如何有效地处理以读取为主的数据
【发布时间】:2010-12-04 18:52:51
【问题描述】:

假设我有一个只有一个字段的演员。每 100 条发送给参与者的消息中有 99 条读取了该值,第 100 条更新了该值。在这种情况下,我想并行处理读取。换句话说,如何使用 Actors 实现读/写锁的性能?这对于 Scala 标准演员或 Akka 是否实用?还是我错过了演员的重点:)

更新:修复了令人困惑的语言,抱歉

【问题讨论】:

  • 不是所有给演员的消息都是只读的(不可变的)吗?演员收到一条消息并根据消息的内容进行一些处理。如果需要,它会在处理过程中向另一个参与者发送消息。
  • 是的,消息是不可变的。想象一下计数器/增量器作为参与者的常见示例:我想知道读取当前值是否可以非阻塞其他读取操作。

标签: scala actor akka


【解决方案1】:

[免责声明:我是 Akka 的 PO]

我建议改用代理,读取可以在任何时候完成,但一次只能写入一次。

http://doc.akkasource.org/agents-scala

编辑:http://doc.akka.io/docs/akka/2.1.0/scala/agents.html(试试这个链接)

【讨论】:

  • +1 代理比尝试在锁上滚动您自己的抽象更简单,并且比 Actor 更适合这个问题。
【解决方案2】:

你很可能错过了演员的重点。我假设您想要一个向其发送查询的参与者,然后它发回响应。向参与者发送消息、处理消息并返回响应涉及到相当多的机器。响应消息的实际生成将作为任务创建并提交到线程池。在消息队列和线程池之间,有多个地方需要锁或最好的 CAS 操作。通常,关键是演员会根据该消息在单独的线程中完成一些工作。

如果您只想读取数据而很少写入数据(例如递增计数器或访问映射中的值),则最好使用 java.util.concurrent 中的适当类。

【讨论】:

    【解决方案3】:

    我假设您的意思是所有消息都是不可变的,并且几乎所有消息都不会改变参与者的状态。在这种情况下,演员可能不是设计的最佳选择。 Actor 允许您管理任何可变状态,就好像您在处理单线程代码一样。

    实际上,每个参与者都有一个邮箱,消息被发送到该邮箱,然后一次处理一个。在您的情况下,这将非常浪费。正如建议的那样,使用 java.util.concurrent 中的某些东西会最有效。

    【讨论】:

      【解决方案4】:

      Actor 旨在串行处理消息。这使得它们很容易推理:您一次收到一条消息,因此参与者中的任何变量(只要它们没有被其他任何人改变)都可以在不考虑并发的情况下进行修改。这是最有效的方法吗?绝对不!但是正常工作的效率较低的代码几乎总是比被破坏的高效代码更好

      您所要求的恰恰相反:您想明确考虑并发性(“我知道 99% 的访问将是读取,因此可以并行发生!”)以提高处理速度。在这种情况下,您可能希望使用java.util.concurrent.locks.ReentrantReadWriteLock 直接控制对可变变量的访问(如果在java.util.concurrent.atomic._ 中找到的访问类型不适合您)。请记住,您现在已经承担了正确锁定的责任,并且要小心谨慎。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-10-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多