c3p0의 ConnectionCustomizer
을 사용하여 응용 프로그램에서 데이터베이스 연결의 생성과 제거를 기록하려고합니다. 이 코드에는 다음과 같은 코드가 있습니다.C3p0의 잠금 주문
log(C3P0Registry.getPooledDataSources())
교착 상태가 발생합니다. c3p0에 동기화 된 메서드를 사용하는 라이브러리의 객체가 두 개 이상 있고 의도 된 잠금 순서를 지정하지 않는 것 같습니다. 연결을 로그 할 때 C3P0Registry
에 잠금 장치가 있고 결국에는 PoolBackedDataSource
(단순히 데이터 소스 목록을 생성하면 잠금을 유발하는 해시 코드에 액세스하는 것입니다).
연결 제공자를 종료하면 (C3P0ConnectionProvider.close()
) 잠금이 반대 순서로 호출됩니다. 그러나 자식 데이터 소스가 종료되는 동안 로깅이 트리거됩니다. 결과는 교착 상태입니다.
내가이 유효 예상 통화량 C3P0 라이브러리로 만드는 중이라서 모두 호출처럼 보인다 :
C3P0ConnectionProvider.close()
C3P0Registry.getPooledDataSources()
또한처럼 보인다
(명시 적으로 문서에 명시하지 않는 한) 자체의 잠금 전략을 관리하는 것은 도서관의 책임이어야합니다. (모범 사례에 대한 나의 이해를 확인하기 위해 누구에게 책임이 있다고 말하지 않습니다.)
이 문제는 어떻게 해결해야합니까? c3p0는보다 현대적인 메커니즘보다는 동기화 된 메소드를 사용하기 때문에 잠금을 실제로 테스트 할 수는 없습니다.
내 DataSource
마감 코드에서 C3P0Registry
잠금을 먼저 잡고 나서 DataSource
을 닫을 수 있습니다. 올바른 잠금 순서를 추측 할 것입니다. 잠금 순서는 내가 편안하다고 느끼는지 모르겠습니다.
로깅 호출의 잠금 순서를 바꿀 수 있다고 생각하지 않습니다. DataSources
의 목록을 얻으려면 C3P0Registry
이 필요합니다. DataSources
을 먼저 잠그지 않고 잠글 수 없으므로 C3P0Registry
을 참조하십시오.
또 다른 해결책은 물론 c3p0 이상의 모든 상위 수준 잠금을 제공하는 것입니다. 연결 풀의 경우, 그 점을 무시하는 것 같습니다.
지금은 로깅을 롤백하고 있습니다. 어떤 도움을 주셔서 감사합니다.
비슷한 것을 경험하고 이에 대한 자세한 정보를 찾았습니까? –
close()를 호출하는 코드 주위에 동기화 된 블록을 추가하여 결국 로깅과 동일한 순서로 잠금을 얻게되었습니다. 그것은 지저분하지만 다시 C3p0의 잠금 전략도 마찬가지입니다. –