我的应用程序有一个没有可变成员的类ApplicationUsers
。在创建实例时,它将整个用户数据库(相对较小)读入不可变集合。它有许多查询数据的方法。
我现在面临着必须创建新用户(或修改其某些属性)的问题。我目前的想法是使用一个高级别的Akka演员:
class UserActor extends Actor{
var users = new ApplicationUsers
def receive = {
case GetUsers => sender ! users
case SomeMutableOperation => {
PerformTheChangeOnTheDatabase() // does not alter users (which is immutable)
users = new ApplicationUsers // reads the database from scratch into a new immutable instance
}
}
}
这样安全吗?我的理由是它应该是:只要users
被SomeMutableOperation
更改,任何使用users
的先前实例的其他线程已经拥有旧版本的句柄,并且不应受到影响。此外,在未安全构建新实例之前,不会对任何GetUsers
请求起作用。
我有什么遗漏的吗?我的构造安全吗?
更新:我可能应该使用Agents来执行此操作,但问题仍然存在:上述安全吗?
答案 0 :(得分:3)
你做得非常正确:拥有不可变数据类型并通过actor中的var
引用它们。这种方式可以自由地共享数据,并且可变性仅限于actor。唯一需要注意的是,如果您从一个在actor之外执行的闭包中引用var
(例如在Future
转换或Props
实例中)。在这种情况下,您需要制作堆栈本地副本:
val currentUsers = users
other ? Process(users) recoverWith { case _ => backup ? Process(currentUsers) }
在第一种情况下,您只需获取值 - 这很好 - 但要求backup
从不同的线程发生,因此需要val currentUsers
。
答案 1 :(得分:1)
对我来说很好看。你似乎不需要代理商。