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)
}
对于这个简单的例子,我的和你的没有区别。但是当系统变得更复杂时,我的代码就不容易出错。
发件人: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)
}
对于这个简单的例子,我的和你的没有区别。但是当系统变得更复杂时,我的代码就不容易出错。