参与者:如何有效地处理主要读取的数据
假设我有一个只有一个字段的演员。每 100 条发送给参与者的消息中,有 99 条会读取该值,第 100 条会更新该值。在这种情况下,我想并行处理读取。换句话说,如何使用Actors来实现读/写锁的性能?这对于 Scala 标准 actor 或 Akka 实用吗?或者我错过了演员的要点:)
更新:修复了令人困惑的语言,抱歉
Suppose I have an actor that has a single field. 99 out of every 100 messages to an actor read the value, and the 100th updates the value. In this case, I would like to process reads in parallel. In other words, how can I achieve the performance of Read/Write locks using Actors? Is this practical with Scala-standard actors or Akka? Or am I missing the point of actors :)
Update: fixed confusing language, sorry
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
[免责声明:我是Akka的PO]
我建议使用Agents代替,读可以在任何时候完成,但一次只能写一次。
http://doc.akkasource.org/agents-scala
编辑:http://doc.akka.io/docs/akka/2.1.0/scala /agents.html(尝试此链接)
[Disclaimer: I'm the PO of Akka]
I suggest using Agents instead, the read can be done at any point, but only one write at a time.
http://doc.akkasource.org/agents-scala
EDIT: http://doc.akka.io/docs/akka/2.1.0/scala/agents.html (try this link)
你很可能没有抓住演员的重点。我假设您想要一个向其发送查询的演员,然后它发回响应。向参与者发送消息、处理消息以及发回响应涉及相当多的机制。响应消息的实际生成将被创建为任务并提交到线程池。消息队列和线程池之间有多个地方需要锁或者最多需要CAS操作。通常,重点是参与者将根据该消息在单独的线程中完成一些工作。
如果您只想读取数据而很少写入数据(例如递增计数器或访问映射中的值),那么最好使用 java.util.concurrent 中的适当类。
You're quite possibly missing the point of actors. I'm assuming you want an actor to which you send a query, and then it sends back a response. There's a fair amount of machinery involved in sending an actor a message, processing it, and sending a response back. The actual generation of the response message will be created as a task and submitted to a thread pool. Between the message queue and the thread pool there are multiple places that require locks or at best CAS operations. Usually the point is that the actor will do some work off in a separate thread based on that message.
If you just want to read and rarely write data (such as incrementing a counter, or access in a value in a map) you'll be much better off using an appropriate class from java.util.concurrent.
我假设您的意思是所有消息都是不可变的,并且几乎所有消息都不会改变参与者的状态。在这种情况下,演员或许并不是设计的最佳选择。 Actor 允许您管理任何可变状态,就像处理单线程代码一样。
实际上,每个参与者都有一个邮箱,消息被发送到该邮箱,然后一次处理一个。在您的情况下,这将非常浪费。正如所建议的,使用 java.util.concurrent 中的东西是最有效的。
I assume you mean that all messages are immutable and that almost all messages do not mutate the state of the actor. In this case, actors are probably not the best choice of design. Actors allow you to manage any mutable state as if you were dealing with single threaded code.
Effectively, each actor has a mailbox to which messages are sent and then processed one at a time. In your scenario, this would be quite wasteful. As suggested, using something from java.util.concurrent would be most effective.
Actor 被设计为串行处理消息。这使得它们很容易推理:您一次收到一条消息,因此参与者中的任何变量(只要它们没有被其他任何人改变)都可以进行修改,而无需考虑并发性。这是最有效的方法吗?绝对不是!但是正常工作的低效代码几乎总是比损坏的高效代码要好。
您所要求的恰恰相反:您想要明确考虑并发性(“我知道 99% 的访问将是读取,因此可以并行发生!”)以获得处理速度。在这种情况下,您可能希望使用 java.util.concurrent.locks.ReentrantReadWriteLock 直接控制对可变变量的访问(如果在 java.util.concurrent.locks 中找到访问类型)。 atomic._ 不适合你)。请记住,您现在已经承担了正确锁定的负担,并且要适当小心。
Actors are designed to process messages serially. This makes them easy to reason about: you get one message at a time, so any variables in the actor (as long as they are not mutated by anyone else) can be modified without thinking about concurrency. Is this the most efficient method? Absolutely not! But somewhat inefficient code that works correctly is almost always better than highly efficient code that is broken.
What you are asking for is the exact opposite: you want to think explicitly about concurrency ("I know that 99% of accesses will be reads and thus can occur in parallel!") in order to gain processing speed. In this case, you probably want to use
java.util.concurrent.locks.ReentrantReadWriteLock
to directly control access to a mutable variable (if the type of access found injava.util.concurrent.atomic._
doesn't work for you). Just remember that you now have taken on the burden of getting locking right, and be appropriately careful.