我已经告诉(斯卡拉)演员从来没有真正在同一时间执行两个操作,这表明该行为(或反应?或接受?)方法本质上是同步的。 我知道在行为方式长时间操作可能导致阻塞的问题,我认为访问消息队列必须以某种方式同步...但是...
什么建议是,一个演员被告知它的消息递增内部计数器会增加计数器的线程安全的方式。 没有两个更新消息将被同时处理,所以没有两个消息可能尝试更新在同一时间计数器。
在演员计数器属性听起来像“共享的状态。”
难道真的是这样的操作将完全线程安全的? 如果是这样,怎么一个演员充分利用多核机器的一些有效的方法? 演员多是怎么线程呢?
如果没有,什么是适当的习惯的方法,而不需要一些同步/ volatile变量来计算在线程方式的消息?
角色模型可以用来与外界隔离的可变状态。 当你有一个可变的状态(例如分配给多个并发进程ID的全球注册),你可以用那个可变的状态了一个演员里面,使客户通过消息传递的演员沟通。 这样,只有演员直接访问可变状态,正如你说的,客户端消息排队读取和处理一个接一个。 对于消息是不可变的非常重要。
为了避免队列变满,该消息处理(这是重要的react
, receive
等)是尽可能的短。 长时间运行的任务应移交给其他演员:
1. Actor A receives a message M from sender S
2. A spawns a new actor C
3. A sends (S, f(M)) to C
4. In parallel:
4a. A starts processing the next message.
4b. C does the long-running or dangerous (IO) task,
When finished, sends the result to S,
and C terminates.
在这个过程中的一些选择:
- C发送
(S, result)
回到阿谁转发至S - A保持的映射
ActorRef C => (Sender S, Message M)
,
以便在情况下它认为C,具有失效 ,它可以重试处理M上有新的演员。
因此,为了回顾一下,一个演员是多线程到多个客户端可以从各个线程发送多条消息的程度,并且它保证了演员将处理连续地所有这些消息(尽管排序可经受各种非过于严格的约束)。
需要注意的是,虽然演员的react
代码可以在不同的线程中执行 ,在它只是一个给定的线程上执行时间的单个特定点(你能想象这样的演员从线程跳转到一个线程调度器认为合适的,但这是一个技术细节)。 注意:内部状态仍然没有需要同步化,因为演员保证之前发生的语义处理消息之间。
并行由具有多个演员并行工作,通常是形成实现监层次结构或平衡的工作量 。
请注意,如果你需要的是并发/异步计算,但您不必或可以摆脱全局状态, Future
s为一个更好的排版和更容易的概念。
“一个演员”不是多线程的,但一个演员系统通常是。 每个演员执行在一个时间只有一个动作,但是当存在多个演员,每可以并行地对各自的包封的状态下操作。 如果它不是参与者之间共享一个计数器属性不共享可变状态。
如果你的问题是关于演员制度的实施,变化而且通常是可配置的,即默认Scala的演员可以被配置为运行任意单线程或线程池或使用Java ForkJoin任务。 我觉得scala.actors源非常可读的,所以我推荐一下,如果你想了解这是怎么回事。
你可以使用一个单独的演员做计数。 当一个演员得到一个消息,它可以发射消息到(单身)计数演员。 这样,你可以有多个工作角色,仍然算的消息。
阿卡有一些所谓的Agents
可能是在这方面非常有用。
val counter = Agent(0)
counter send (_ + 1)
http://doc.akka.io/docs/akka/2.0.2/scala/agents.html