我有一个将调用委托给有状态单身人士的演员。单例是有状态的,因为它维护着一个对象图。这个单例对象只用在actor和一个类(不是actor)中,我在这个地图中检索一个对象(所以只是线程安全读取)。
class MyActor extends Actor{
def receive()={
case ACase => singleton.amethod()
case BCase => singleton.bmethod()
}
}
val singleton = new MyActorLogic
class MyActorLogic{
val map:Map[String, Object] = Map()
def amethod()=//alter the map
def readMap(value:String) = map(value) }
可能有任何副作用/问题吗? 感谢
答案 0 :(得分:9)
答案 1 :(得分:3)
理论上,使用来自多个线程的简单可变映射的MyActorLogic
可能会导致并发修改异常(当一个线程遍历映射时,另一个线程正在修改它)。
您可以执行以下操作以避免出现问题:
Akka
中,您没有直接使用Actor
实例(而是通过代理访问它 - ActorRef
)。在这种情况下,演员不仅可以保证对地图的安全访问,它总是一次处理一条消息 - 其他线程即使通过反射也无法访问私有成员。MyActorLogic
线程安全的更新/检索方法(例如,使它们成为synchronized
)ConcurrentHashMap
val map:mutable.Map
代替var map:immutable.Map
。因此,访问map
的多个线程有时可能会使用陈旧数据,但不会有并发修改(写时复制方法)。只是为了说明,真正的单身人士将是:
object MyActorLogic{
val map:Map[String, Object] = Map()
...