5

我有一个演员正在将调用委托给有状态的单身人士。单例是有状态的,因为它维护着一个对象映射。这个单例对象仅在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)    }                

会不会有任何副作用/问题?谢谢

4

2 回答 2

9

不要以任何理由这样做相信我。

如果您需要那种东西,请改用 Agent,这就是它们的好处:

http://doc.akka.io/docs/akka/2.0.4/scala/agents.html

于 2011-03-04T15:11:51.753 回答
3

理论上,MyActorLogic从多个线程使用带有简单可变映射的 ,可能会导致并发修改异常(当一个线程正在遍历映射,而另一个线程正在修改它时)。

您可以执行以下操作以避免出现问题:

  1. 将地图放入actor(作为私有成员)。在Akka中,您不是Actor直接使用实例(而是通过代理访问它 - ActorRef)。在这种情况下,对地图的安全访问不仅由参与者保证,而且总是一次处理一条消息——即使通过反射,其他线程也无法访问私有成员。
  2. 您可以制作MyActorLogic线程安全的更新/检索方法(例如,制作它们synchronized
  3. 你可以用旧好的ConcurrentHashMap
  4. 而不是val map:mutable.Map你可以使用var map:immutable.Map. 因此,多个线程访问map可能偶尔会处理陈旧的数据,但不会有并发修改(写时复制方法)。

只是为了说明,真正的单身人士将是:

object MyActorLogic{
 val map:Map[String, Object] = Map()
 ...
于 2011-03-04T08:26:37.993 回答