문제

Java Dao의 메소드에서 '동기화 된'키워드를 사용하면 웹 응용 프로그램에서 사용할 때 문제가 발생합니까?

여기에서 볼 수 있듯이 리소스 충돌을 피하기 위해 동기화 된 방법이 필요한 다중 스레드 스탠드 혼자 응용 프로그램이 있기 때문에 묻습니다.

java.util.concurrent.ExecutionException: javax.persistence.PersistenceException: org.hibernate.HibernateException: Found shared references to a collection: com.replaced.orm.jpa.Entity.stuffCollection

내가 걱정하는 것은 상당수의 사람들이 동기화 된 메소드가 전체 응용 프로그램을 차단하고 느리게하는 응용 프로그램을 사용하려고 할 때입니다.

Spring Injected JPA Entity Manager Factory를 사용하고 있는데, 이는 DAO에 엔터티 관리자를 제공합니다. 기술적으로 DAO 레이어를 제거하고 클래스가 Entity Manager Factory를 직접 호출하도록 할 수 있지만 DAO가 제공하는 분리를 즐깁니다.

또한 연결된 엔티티 ORM 객체를 스레드 사이에 전달하지 않도록 매우 조심하고 있습니다. DAO에 액세스 할 때 리소스 충돌 오류가 발생한다고 추측합니다. 나는 여러 스레드가 동시에 진행되고 있다고 생각하며 데이터베이스에서 비 원자 방식으로 읽거나 읽으려고 노력합니다.

이 경우 DAO를 사용하여 더 많은 해를 끼칠 수 있는데 도움을 드릴까요?


내가 의문에서 제외한 큰 정보는 DAO가 싱글 톤이 아니라는 것입니다. 내가 그 세부 사항을 포함 할만 큼 명쾌하게 생각했다면 아마도 처음에는 질문을하지 않았을 것입니다.

내가 올바르게 이해하면 Spring 은이 클래스를 사용하는 각 클래스마다 새로운 DAO 클래스 인스턴스를 만듭니다. 따라서 백킹 엔티티 관리자는 각 스레드마다 고유해야합니다. Rob H가 대답 하듯이 엔티티 관리자를 공유하지 않는 것은 여기서 핵심입니다.

그러나 이제 동기화 된 것을 제거 할 때 왜 오류가 발생하는지 이해하지 못합니다.


이것에 따르면 , @PersistEnceContext 주석은 스레드 -SAFE SharedEntityManager를 만듭니다. 따라서 싱글 톤 다오를 만들 수 있어야합니다.

도움이 되었습니까?

해결책

당신은 당신이 스레드에서 엔티티 객체를 공유하지 않는다고 말합니다. 좋아요. 그러나 당신은 또한 당신이 공유하지 않는지 확인해야합니다 EntityManager 물체 (또는 세션 실을 가로 지르는 최대 절전 모드). Spring과 같은 프레임 워크는 스레드-로컬 변수에 세션을 저장하여 자동으로 귀하를 위해이를 관리합니다. 프레임 워크의 도움없이 자신의 DAO를 코딩하는 경우 공유를 피하기 위해 예방 조치를 취해야합니다.

이 작업을 수행하면 대화 상태가 스레드에서 공유되지 않기 때문에 DAO 메소드를 동기화 할 이유가 없어야합니다. 이는 동시 웹 응용 프로그램에 중요합니다. 대안은 하나의 스레드만이 동일한 DAO 인스턴스를 공유한다고 가정 할 때 한 번에 DAO에 액세스 할 수 있다는 것입니다. 처리량에 전혀 좋지 않습니다.

다른 팁

스레드 안전을 위해 동기화 해야하는 경우 그대로 두십시오. 어쨌든이 경우 차단이 필요합니다. 웹 애플리케이션 케이스에 차단이 필요하지 않은 경우 다음을 수행 할 수 있습니다.

  • 잠금 장치에 경쟁이 없을 때 성능이 적용되는 것은 무시할 수 있고 데이터베이스에 부딪히는 비용을 고려할 때 무의미하지 않기 때문에 그대로 두십시오.
  • 기본 비 동기화 된 DAO를 보호하는 독립형 애플리케이션 케이스에 동기화 레이어를 추가하도록 재 설계하십시오.

개인적으로, 나는 그것을 그대로 남겨두고 당신이 리팩터를 리팩터 해야하는지 확인하기 위해 그것을 프로파일 할 것입니다. 그때까지 당신은 단순히 조기 최적화를하고 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top