来自: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 }
}
}
Run Code Online (Sandbox Code Playgroud)
是否可能会有多个同时接收的呼叫,使得计数值不确定.
我的理解是,这种安全的唯一方法就是如果对这个对象的接收调用是自己做的互斥.
多线程永远不会同时调用receive方法.驻留在Actor邮箱中的邮件由receive方法一次一个地处理.多个其他Actors或ActorSystem之外的函数可以同时将消息排入Actor的邮箱,但ActorSystem最终会对消息进行排序.来自文档:
入队以发送操作的时间顺序发生,这意味着由于跨线程分配actor的明显随机性,从不同的actor发送的消息可能在运行时没有定义的顺序.
接收方法的串行处理由您从未实际从ActorSystem获取Actor值(具有接收)的事实得到保证.相反,你只得到一个没有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!
Run Code Online (Sandbox Code Playgroud)
"调用"receive方法的唯一方法是向ActorRef发送消息:
actorRef ! Foo //non-blocking, enqueues a Foo object in the mailbox
Run Code Online (Sandbox Code Playgroud)
回到你的问题:ActorSystem充当所有Actor实例的伪互斥.
因此,示例中的代码绝对安全,并且只能在任何给定时间通过一条消息访问状态.