Akka演员的执行是静音的吗?

Akka演员的执行是静音的吗?,akka,Akka,发件人: 表明这是安全的: class FooCounter extends Actor { var count: Long = 0 def receive = { case Foo => { count += 1} case FooCountRequest => { sender ! count } } } 是否有可能同时接收多个呼叫,从而使count的值不确定 我的理解是,唯一安全的方法是,如果对该对象的receive调用本身是互斥的。多个线程从未

发件人: 表明这是安全的:

class FooCounter extends Actor {
  var count: Long = 0

  def receive = {
    case Foo => { count += 1}
    case FooCountRequest => { sender ! count }
  }
}
是否有可能同时接收多个呼叫,从而使count的值不确定


我的理解是,唯一安全的方法是,如果对该对象的receive调用本身是互斥的。

多个线程从未同时调用receive方法。驻留在参与者邮箱中的邮件由receive方法一次处理一次。多个其他参与者或ActorSystem之外的函数可以同时将消息排入参与者邮箱的队列,但ActorSystem最终会对消息进行排序。从:

排队按发送操作的时间顺序进行,这意味着 不同参与者发送的消息可能没有定义的顺序 由于分布参与者的明显随机性,在运行时 跨越线程

receive方法的串行处理是由这样一个事实保证的,即您从未实际从ActorSystem获得Actor值(具有receive)。相反,您只会得到一个没有receive方法的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!
“调用”receive方法的唯一方法是向ActorRef发送消息:

actorRef ! Foo //non-blocking, enqueues a Foo object in the mailbox
回到您的问题:ActorSystem充当所有Actor实例的伪互斥体


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

完全同意Ramon的观点。你可以想象在你家外面有一个邮箱(
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)

}

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

多谢各位。这是非常有用的。因此,这听起来像是参与者的主要好处,实际上不是启用并发性,而是确保并发系统中操作的序列化。每个参与者一次可以处理一条消息,因此使用多个参与者可以得到并发处理。嗯。。。。在里面此http服务器一次只处理一个请求?是的,因为该设计只实例化了一个ActorRef。但是actor非常轻量级,大约有400字节的内存开销。这使得开发者可以创造数百万美元,如果他们愿意的话。