假设我有一个只有一个字段的演员。每 100 条发送给参与者的消息中有 99 条读取该值,第 100 条更新该值。在这种情况下,我想并行处理读取。换句话说,如何使用 Actors 实现读/写锁的性能?这对于 Scala 标准演员或 Akka 是否实用?还是我错过了演员的重点:)
更新:修复了令人困惑的语言,对不起
[免责声明:我是Akka的PO]
我建议改用代理,读取可以在任何时候完成,但一次只能写入一次。
http://doc.akkasource.org/agents-scala
编辑:http ://doc.akka.io/docs/akka/2.1.0/scala/agents.html (试试这个链接)
你很可能错过了演员的重点。我假设您想要一个向其发送查询的参与者,然后它会发回响应。向参与者发送消息、处理消息并返回响应涉及到相当多的机器。响应消息的实际生成将作为任务创建并提交到线程池。在消息队列和线程池之间,有多个地方需要锁或充其量是 CAS 操作。通常重点是参与者将根据该消息在单独的线程中完成一些工作。
如果您只想读取而很少写入数据(例如递增计数器或访问映射中的值),则最好使用 java.util.concurrent 中的适当类。
我假设您的意思是所有消息都是不可变的,并且几乎所有消息都不会改变参与者的状态。在这种情况下,演员可能不是设计的最佳选择。Actor 允许您管理任何可变状态,就像您在处理单线程代码一样。
实际上,每个参与者都有一个邮箱,消息被发送到该邮箱,然后一次处理一个。在您的情况下,这将是非常浪费的。正如所建议的那样,使用 java.util.concurrent 中的某些东西是最有效的。
Actor 旨在串行处理消息。这使得它们很容易推理:您一次收到一条消息,因此参与者中的任何变量(只要它们没有被其他任何人改变)都可以在不考虑并发的情况下进行修改。这是最有效的方法吗?绝对不!但是,正常工作的低效代码几乎总是比被破坏的高效代码要好。
您所要求的恰恰相反:您想明确考虑并发性(“我知道 99% 的访问将被读取,因此可以并行发生!”)以提高处理速度。在这种情况下,您可能希望使用java.util.concurrent.locks.ReentrantReadWriteLock
直接控制对可变变量的访问(如果找到的访问类型java.util.concurrent.atomic._
不适合您)。请记住,您现在已经承担了正确锁定的责任,并且要小心谨慎。