지난 시간에는 싱글톤의 개념과 기본적인 구현 방법
멀티 쓰레드 환경에서 thread - safe 하게 구현하기
그리고 이른 초기화에 대해서 알아보았습니다
이번 시간에는 JAVA 에서 권장하는 방법들과
더불어 1 장에서 다뤘던 개념들의 단점들을
보완하기 위해 나온 방안들을 살펴보겠습니다
Double Checked Locking
멀티 쓰레드 환경에서 이른 초기화처럼 객체를 미리 생성하지 않으면서
synchronized 의 성능 이슈 또한 사전에 방지할 수 있는 기법입니다
Double Checked Locking
public class GlobalSettings {
private static volatile GlobalSettings instance;
private GlobalSettings() {}
public static GlobalSettings getInstance() {
if (instance == null) { // 1st gate
synchronized (GlobalSettings.class) { // 2nd gate
if (instance == null) { // 3rd gate
instance = new GlobalSettings();
}
}
}
return instance;
}
}
1st gate
instance 의 null 여부를 체크합니다
instance 가 이미 존재하는 경우(대부분의 경우)
synchronized 에 진입하지 않기 때문에 성능 저하에 대한 우려가 낮습니다
2nd gate
1st gate 를 통과했을 때만 진입합니다
synchronized 키워드를 이용하여 thread - safe 환경을 만들고
동기화를 위해 리터럴로 GlobalSettings.class 를 적습니다
3rd gate
1st gate, 2nd gate 를 통과했을 때만 진입합니다
synchronized 블록 안에서 다시 한번 instance 의 null 여부를 체크합니다
다른 쓰레드가 락을 넘겨주기 전에 instance 를 생성했을 수도 있는 경우를 대비합니다
Double Checked Locking 을 사용할 경우 멀티 쓰레드 환경에서 성능은 개선되지만
단점으로는 다소 복잡한 구현과 함께 JAVA 5 이상에서의 volatile 의 제한적인 메모리 모델이 언급됩니다
Static Inner Class (Initialization-on-demand holder idiom)
static inner class 를 사용하는 방법은 initialization on demand holder idiom 으로 알려져 있으며
클래스의 로딩과 초기화를 지연시키고
JVM 의 클래스 초기화 메커니즘을 통해 thread - safe 를 제공합니다
Static Inner Class (Initialization on demand holder idiom)
public class GlobalSettings {
private GlobalSettings() {}
private static class Holder {
private static final GlobalSettings INSTANCE = new GlobalSettings();
}
public static GlobalSettings getInstance() {
return Holder.INSTANCE;
}
}
private 생성자
싱글톤의 기본 개념으로 생성자는 private 으로 선언합니다
따라서 인스턴스의 생성은 전적으로 클래스 내부에서 통제됩니다
Static Inner Class (Holder) - (Lazy Initialization)
Holder 클래스 내부에서 인스턴스가 생성됩니다
GlobalSettings.getInstance() 가 호출되기 이전에는
Holder 클래스가 로드되지 않으며 인스턴스 또한 생성되지 않습니다
이는 싱글톤의 인스턴스 생성을 지연시키는 효과를 지닙니다(lazy initialization)
Holder 클래스에서 static final 로 선언된 인스턴스는
JVM 차원에서 한 번만 수행되며 이후로는 동일한 인스턴스가 반환되므로
별도의 synchronized 키워드나 락이 필요하지 않습니다
Thread - safe
앞선 특징과 동일한 이유로 static final 필드의 초기화는
JAVA 클래스 초기화 메커니즘을 통해 thread - safe 하게 처리됩니다
오늘은 싱글톤의 심화적인 내용들을 다루어 보았습니다
다음 시간에는 다른 디자인 패턴을 가지고 찾아오도록 하겠습니다
'Computing and DB 🖥 > Computer Science' 카테고리의 다른 글
[디자인 패턴] 싱글톤 제 1장 - "개념 및 멀티 쓰레드와 이른 초기화" (0) | 2024.01.24 |
---|---|
정적 콘텐츠(Static Content) & 동적 콘텐츠(Dynamic Content) (0) | 2024.01.12 |
Web Server 는 뭐고, WAS 는 도대체 뭐야? (0) | 2024.01.08 |
테스트 코드 작성하기가 귀찮다고? (0) | 2024.01.02 |
캐시(cache)랑 쿠키(cookie)는 뭐가 다른 거야? (0) | 2023.12.16 |