为什么我应该使用context.become()在Actor中存储内部状态?

mul*_*lya 3 scala actor akka

我已经阅读了scala-best-practices,并提出了一个有关“ 5.2。应该仅使用context.become改变演员中的状态”的问题。我不明白为什么使用来存储内部状态如此糟糕var。如果actor按顺序执行所有消息,我将看不到任何问题来源。我想念什么?

Jef*_*ung 6

请考虑您引用的文章中的一个示例:

class MyActor extends Actor {
  val isInSet = mutable.Set.empty[String]

  def receive = {
    case Add(key) =>
      isInSet += key

    case Contains(key) =>
      sender() ! isInSet(key)
  }
}
Run Code Online (Sandbox Code Playgroud)

此示例没有天生的不正确之处,因此您缺少一些重要的了解。如你所知,一个演员在处理其邮箱的邮件顺序,因此它安全的,代表其状态在内部变量和变异这种状态下,只要演员不公开该州1

become通常用于动态切换角色的行为(例如,更改角色处理的消息的类型)和/或其状态。在本文的第二个示例中,参与者的状态以其行为编码为参数。这是第一个示例的优雅替代方案,但是在这种简单情况下,这是一个优先选择的问题。

become但是,可以真正发挥作用的一个场景是具有许多状态转换的参与者。如果不使用become,则主体中的参与者逻辑receive会变得难以管理,甚至变成if-else陈述的丛林。作为用于become对状态转换进行建模的示例,请查看此示例项目,该示例项目“用餐哲学家”问题进行了建模。


1一个潜在的问题是,虽然isInSet是a val,但它是可变的Set,因此如果参与者将这种状态暴露给参与者自身之外的某种事物(在示例中未这样做),则会发生奇怪的事情。例如,如果演员Set以消息的形式将此消息发送给另一个演员,则外部演员可以更改此状态,从而导致意外的行为或竞赛条件。可以通过将更val改为a var,将可变的Set更改为不可变,来缓解此问题Set