2013-02-04 3 views
1

Java의 다중 스레딩에 익숙하지 않습니다. 내가 원한 것은 코드 블록에 대한 잠금을 설정하는 것이다. 내 경우에는 특정 사용자에 대해 일부 동기화를 수행하는 동안 낙관적 인 잠금 예외를 피하기를 원합니다. 메서드 replicateUser은 동일한 사용자에 대해 여러 스레드에서 호출 할 수 있습니다. 그러나 보장되지는 않으며 authenticatedUser은 항상 동일한 동일한 개체입니다.낙관적 인 잠금 예외를 피하기 위해 코드 블록을 효율적으로 잠그는 방법

어떻게이 섹션을 효과적으로 잠글 수 있습니까? 내가 싫어하는 것은 섹션이 모든 스레드에 대해 잠겨 있지만 동일한 사용자가있는 스레드에만 해당된다는 것입니다. getUserName()을 사용하여 아래 예제와 같이 문자열 개체에 잠금을 설정할 수 있습니까? authenticatedUser.getUserName().intern()

private void replicateUser(AuthenticatedUser authenticatedUser) { 
    // 
    // How to synchronize the following block correctly? 
    // 
    synchronized (authenticatedUser.getUserName()) { 
     User dbUser = userRepository.findOne(authenticatedUser.getUserName()); 
     if (!checkIsUserReplicated(authenticatedUser, dbUser)) { 
      doReplication(dbUser); 
     } 
    } 
} 
+0

낙관적 인 잠금 예외에 대한 세부 정보를 제공하려고하면이 블록은 해결되지 않습니다. –

+0

@ Vash 해결책이라면이 질문을 게시하지 않았을 것입니다! 내 질문에 다른 말로하실 수 있습니다 : 솔루션은 여러 스레드가 db에 동일한 레코드를 작성하지 않도록하는 것입니다. 왜냐하면 만약 그렇다면, 낙관적 인 락 예외가 생길 수 있기 때문에 ... 나는 동기화 된 블록 위에 위의 명령을 더 명확하게하기 위해 업데이트했다. – fischermatte

+0

이것을위한 방법을 찾아 냈는가? 나는 또한 같은 조건을 가지고있다. 나는 이미 동일한 사용자 ID에 대해 실행중인 스레드가있을 때만 서비스의 내 메소드 중 하나를 잠글 수 있어야합니다. 다른 사용자 ID가 나타나면 잠글 수 없습니다. – roanjain

답변

1

당신에게 더 나은 넣어 잠금 장치는 두 개의 문자열을 내용으로 동일하면, intern() 그들을 위해 동일한 개체를 반환 보장되기 때문이다. 그것은 하나의 인스턴스 만 특정 사용자 이름을 가진 클래스 AuthenticatedUser의가 있음을, 시스템에 보장되어있는 경우

또한, 당신은 authenticatedUser에 직접 잠글 수 있습니다.

1

언급 한 바와 같이 authenticatedUser.getUserName()에서 동기화하는 것은 authenticatedUser의 여러 인스턴스가있을 수 있기 때문에 작동하지 않습니다. 동일한 authenticatedUser 데이터에서 읽는 두 개의 스레드는 다른 EntityManager 컨텍스트에서 읽으면 다른 인스턴스를 갖게됩니다. 이 문제를 해결하려면 doReplication 메소드를 try/catch 블록으로 래핑하여 때때로 다른 optimistic 변경 사항 (em.refresh 사용)이 변경되었는지 확인하거나 사용법으로 전환 할 수있는 optimistic 잠금 예외를 고려할 수 있습니다 여기에 설명 된 바와 같이 비관적 잠금 : 당신이 authenticatedUser을 고정하면 http://wiki.eclipse.org/EclipseLink/Examples/JPA/Locking#Pessemistic_Locking http://wiki.eclipse.org/EclipseLink/Examples/JPA/PessimisticLocking

, 당신은이 복제 된 경우 확인하고 잠금을 해제하거나 복제를 수행 할 수 있습니다.