Akka 演员执行是否互斥?

Is Akka actor execution mutexed?

发件人:https://www.chrisstucchio.com/blog/2013/actors_vs_futures.html 表明这是安全的:

class FooCounter extends Actor {
  var count: Long = 0

  def receive = {
    case Foo => { count += 1}
    case FooCountRequest => { sender ! count }
  }
}

会不会有多个同时调用receive,使得count的值不确定

我的理解是,如果对此对象的接收调用与其自身互斥,唯一安全的方法就是。

接收方法永远不会被多个线程同时调用。驻留在 Actor 邮箱中的消息由 receive 方法一次处理一个。多个其他 Actor 或 ActorSystem 之外的功能可以同时将消息排队到 Actor 的邮箱,但 ActorSystem 最终会对消息进行排序。来自 docs:

Enqueuing happens in the time-order of send operations, which means that messages sent from different actors may not have a defined order at runtime due to the apparent randomness of distributing actors across threads.

receive 方法的串行处理由您从未真正从 ActorSystem 获得 Actor 值(具有接收)这一事实来保证。相反,您只会得到一个没有接收方法的 ActorRef:

val actorSystem = akka.actor.ActorSystem()

//not an Actor but an ActorRef
val actorRef : ActorRef = actorSystem actorOf Props[FooCounter]

actorRef.receive(Foo) //COMPILE TIME ERROR!

接收方法 "invoke" 的唯一方法是向 ActorRef 发送消息:

actorRef ! Foo //non-blocking, enqueues a Foo object in the mailbox

关于您的问题:ActorSystem 充当所有 Actor 实例的伪互斥锁。

因此,您示例中的代码是绝对安全的,并且在任何给定时间只能由一条消息访问该状态。

完全同意拉蒙的观点。你可以想象它在你家外面有一个邮箱(Actor),邮件通过你的地址(ActorRef)送到你的邮箱,你家里只有一个人照顾您的邮件一次一个

此外,为了更实用的风格和保持代码的不变性。我会改为执行以下操作:

class FooCounter extends Actor {

  def _receive(count: Long): Receive = {
    case Foo => 
      context.become(_receive(count + 1))

    case FooCountRequest => 
      sender() ! count
  }

  def receive = _receive(0L)

}

对于这个简单的例子,我的和你的没有区别。但是当系统变得更复杂时,我的代码就不容易出错。