2013-05-11 2 views
1

내 응용 프로그램에는 변경 가능한 구성원이없는 클래스 ApplicationUsers이 있습니다. 인스턴스를 생성하면 전체 사용자 데이터베이스를 비교적 작은 규모의 불변 인 컬렉션으로 읽습니다. 데이터를 쿼리하는 데는 여러 가지 방법이 있습니다.var을 공유하는 것이 안전 할 수 있습니까?

이제 새로운 사용자를 만들거나 (일부 속성을 수정해야하는) 문제에 봉착했습니다. 현재 나의 생각은 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 
    } 
    } 
} 

안전한가요? 내 생각에 다음과 같아야합니다 : SomeMutableOperation에 의해 users이 변경 될 때마다 users의 이전 인스턴스를 사용하는 다른 스레드는 이미 이전 버전을 처리하므로 영향을받지 않아야합니다. 또한 GetUsers 요청은 새 인스턴스가 안전하게 구성 될 때까지 적용되지 않습니다.

누락 된 항목이 있습니까? 내 구조는 안전한가요?

업데이트 : 나는 이것을 수행하기 위해 Agents을 사용해야 할 것입니다. 그러나 질문은 여전히 ​​유효합니다. 위의 사항이 안전합니까?

답변

3

당신은 올바르게하고 있습니다 : 불변의 데이터 유형을 가지고 액터 내에 var을 통해 참조하십시오. 이 방법으로 자유롭게 데이터를 공유 할 수 있으며 가변성은 액터에만 국한됩니다. 조심해야 할 점은 액터 바깥에서 실행되는 클로저 (예 : Future 변형 또는 Props 인스턴스)에서 var을 참조하는 것입니다. 이 경우 당신은 스택 로컬 복사본을 만들 필요가 : 방금 잡아 첫 번째 경우

val currentUsers = users 
other ? Process(users) recoverWith { case _ => backup ? Process(currentUsers) } 

을 가치 미세하지만 backup를 요구하는 것은, 다른 스레드에서 따라서 필요성을 일입니다 val currentUsers입니다.

1

나에게 잘 보입니다. 여기에 요원이 필요없는 것 같습니다.

+0

감사합니다. 나는 에이전트가 내 코드를 단순화하고 (위의 구문을 만들 필요가 없음) 데이터베이스의 업데이트를 자연스럽게'users' 객체의 업데이트와 분리 할 것이라고 생각합니다. 내 경우에는 더 나은 디자인이 될 것입니다. – Eduardo

+0

에이전트와 관련된 문제는 그들이 실행중인 노드 (jvm)에만 국한된다는 것입니다. 다른 노드에 원격으로 전달할 수 없습니다. 이렇게하면 시스템을 수평 확장하려는 경우 문제가 발생할 수 있습니다. – Bacon

관련 문제