자바 에서 단일 모드 를 어떻게 정확하게 쓰 는 지 상세 하 게 설명 합 니 다.
청동 5:(Lazy-loaded,하지만 라인 이 안전 하지 않 음)
하나의 사례 모델 을 실현 하 겠 다 는 질문 에 많은 사람들의 첫 반응 은 다음 과 같은 코드 를 쓰 는 것 이 었 다.교과서 에서 도 이렇게 가 르 쳤 다.
public class Singleton {
private static Singleton instance;
private Singleton(){}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
이 코드 는 간단명료 하고 지연 로드 모드 를 사 용 했 지만 라인 이 안전 하지 않 습 니 다.다 중 스 레 드 환경 에서 getInstance()방법 을 호출 하면 여러 스 레 드 가 if 구문 에 들 어 가 는 프로그램 코드 블록 이 발생 할 수 있 습 니 다.게으름뱅이 식:synchronized(Lazy-loaded,라인 은 안전 하지만 효율 적 이지 않 음)
위의 문 제 를 해결 하기 위해 서 가장 쉬 운 방법 은 전체 getInstance()방법 을 동기 화(synchronized)로 설정 하 는 것 입 니 다.
public class Singleton {
private static Singleton instance;
private Singleton() {}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
스 레 드 안전,로드 지연 을 했 지만 효율 적 이지 않 습 니 다.getInstance()방법 은 언제든지 하나의 스 레 드 만 호출 할 수 있 기 때 문 입 니 다.그러나 synchronized 작업 은 첫 번 째 호출 때 만 필요 합 니 다.즉,첫 번 째 인 스 턴 스 대상 을 만 들 때 입 니 다.이 모드 는 단일 생 성 이 끝 난 후에 도 매번 하나의 스 레 드 만 getInstance()방법 에 접근 할 수 있 고 잠재 적 인 성능 문 제 를 초래 할 수 있 습 니 다.이중 검사 자 물 쇠 를 끌 어 냈 다.굶 주 린 사람:static final field(Lazy-loaded 가 아 닌)
이 방법 은 매우 간단 합 니 다.하나의 인 스 턴 스 가 static final 로 설명 되 어 있 기 때문에 처음으로 메모리 에 클래스 를 불 러 올 때 초기 화 되 기 때문에 인 스 턴 스 대상 을 만 드 는 것 은 스 레 드 가 안전 합 니 다(JVM 에서 보증 합 니 다).
public class Singleton{
//
private static final Singleton instance = new Singleton();
private Singleton(){}
public static Singleton getInstance(){ // Singleton with static factory
return instance;
}
}
이것 은 게 으 른 로 딩 모드 가 아 닙 니 다.인 스 턴 스 는 로 딩 클래스 를 불 러 온 후에 처음부터 초기 화 됩 니 다.클 라 이언 트 가 getInstance()방법 을 호출 하지 않 더 라 도.이 로 인해 일부 사용 제한 이 생 길 수 있 습 니 다.예 를 들 어 Singleton 인 스 턴 스 의 생 성 은 매개 변수 나 설정 파일 에 의존 하 는 것 입 니 다.getInstance()전에 특정한 방법 으로 파 라 메 터 를 설정 해 야 합 니 다.그러면 이러한 단일 쓰기 방법 은 사용 할 수 없습니다.비슷 한 방법 은 다음 과 같다.
public class Singleton{
public static final Singleton instance = new Singleton(); // Singleton with public final field
private Singleton(){}
}
// <Effective Java> 14
이중 검사 자물쇠+volatile(Lazyload,스 레 드 는 안전 하지만 난해 함)이중 검사 잠 금 모드(double checked locking pattern)는 동기 블록 에 잠 금 을 추가 하 는 방법 입 니 다.프로그래머 는 인 스 턴 스=null 을 두 번 검사 하기 때문에 이중 검사 자물쇠 라 고 부 릅 니 다.한 번 은 동기 블록 밖 에 있 고 한 번 은 동기 블록 안에 있 습 니 다.왜 동기 블록 안에서 다시 한 번 검사 해 야 합 니까?동기 블록 밖의 if 에 여러 개의 스 레 드 가 함께 들 어 갈 수 있 기 때문에 동기 블록 에서 2 차 검 사 를 하지 않 으 면 여러 개의 인 스 턴 스 대상 이 생 성 됩 니 다.
public static Singleton getSingleton() {
if (instance == null) { //Single Checked
synchronized (Singleton.class) {
if (instance == null) { //Double Checked
instance = new Singleton();
}
}
}
return instance ;
}
이 코드 는 보기에 매우 완벽 해 보이 지만,애석 하 게 도 그것 은 문제 가 있다.주로 인 스 턴 스=new Singleton()이라는 말 이 있 습 니 다.이것 은 원자 조작 이 아 닙 니 다.사실은 JVM 에서 이 말 은 다음 과 같은 세 가지 일 을 했 습 니 다.인 스 턴 스에 메모리 할당
public class Singleton {
private volatile static Singleton instance; // volatile
private Singleton(){}
public static Singleton getSingleton() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
그러나 특히 자바 1.5 이전 버 전에 서 volatile 의 쌍 검 자 물 쇠 를 사용 한 것 은 문제 가 있 습 니 다.이 문 제 는 자바 1.5 에서 복 구 될 수 있 기 때문에 그 후에 야 volatile 을 안심 하고 사용 할 수 있 습 니 다.정적 내부 클래스:IoDH,initialization-on-demand holder
이 모델 은 자바 의 정적 내부 클래스 와 다 중 스 레 드 부족 동기 화 잠 금 지식 을 종합 적 으로 사용 하여 로드 지연 과 스 레 드 안전 을 교묘 하 게 동시에 실현 했다.
public class Singleton {
private Singleton() {}
private static class LazyHolder {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() { // From wikipedia
return LazyHolder.INSTANCE;
}
}
정적 내부 클래스 는 외부 클래스 의 static 부분 에 해당 하 며,대상 은 외부 클래스 대상 에 의존 하지 않 기 때문에 직접 만 들 수 있 습 니 다.정적 내부 클래스 는 처음 사 용 될 때 만 전 재 됩 니 다.다 중 스 레 드 부족 동기 화 잠 금
다 중 스 레 드 개발 에서 병발 문 제 를 해결 하기 위해 주로 synchronized 를 사용 하여 상호 배척 자 물 쇠 를 추가 하여 동기 화 통 제 를 하 는 것 을 잘 알 고 있 습 니 다.그러나 어떤 경우 에는 JVM 이 은밀하게 동기 화 를 실 행 했 기 때문에 수 동 으로 동기 화 제 어 를 할 필요 가 없습니다.이러한 상황 은 다음 과 같다.
1.정적 초기 화기(정적 필드 나 static{}블록의 초기 화기)에서 데 이 터 를 초기 화 할 때
2.final 필드 에 접근 할 때
3.스 레 드 를 만 들 기 전에 대상 을 만 들 때
4.스 레 드 가 처리 할 대상 을 볼 수 있 을 때
열거 하 다.
자바 1.5 부터 하나의 요 소 를 포함 하 는 매 거 진 형식 만 작성 하 십시오:
public enum Singleton {
INSTANCE;
}
이런 방법 은 기능 적 으로 공유 역 방법 과 비슷 하지만 더욱 간결 하고 무상 으로 서열 화 메커니즘 을 제공 하여 여러 차례 의 실례 화 를 절대적 으로 방지한다.복잡 한 서열 화 나 반사 공격 을 할 때 도.이런 방법 은 아직 널리 사용 되 지 않 았 지만 단일 요소 의 매 거 진 유형 과 싱글 톤 을 실현 하 는 가장 좋 은 방법 이 되 었 다.다음은 몇 가지 세부 적 인 의문 을 제기 하 는 실현 방법 이다.
1.static final 어떤 디 테 일이 있 는 지
2.static field 의 할당 초기 화 는 static 코드 블록 과 선후 가 있 습 니까?
3.정적 내부 클래스 의 단일 모드 를 어떻게 쓰 는 지
4.P50 in 자바 EE 디자인 모델 분석 과 응용 중의 예 는 정말 Lazyload 효과 가 있 습 니까?
이상 은 본 고의 모든 내용 입 니 다.본 고의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 도움 이 되 기 를 바 랍 니 다.또한 저 희 를 많이 지지 해 주시 기 바 랍 니 다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
JPA + QueryDSL 계층형 댓글, 대댓글 구현(2)이번엔 전편에 이어서 계층형 댓글, 대댓글을 다시 리팩토링해볼 예정이다. 이전 게시글에서는 계층형 댓글, 대댓글을 구현은 되었지만 N+1 문제가 있었다. 이번에는 그 N+1 문제를 해결해 볼 것이다. 위의 로직은 이...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.