헤드퍼스트 디자인패턴 5. 싱글턴 패턴스터디2024. 12. 11. 19:49
Table of Contents
싱글턴을 생성하는 여러 가지 방법
가장 기본적인 방법
public class BasicSingleton {
private static BasicSingleton instance;
private BasicSingleton() {
// private constructor to prevent instantiation
}
public static BasicSingleton getInstance() {
if (instance == null) {
instance = new BasicSingleton();
}
return instance;
}
}
멀티 쓰레드 환경에서 문제가 발생할 수 있다. 여러 스레드가 동시에 getInstance()
를 호출하면 여러 개의 인스턴스가 생성될 수 있다.
단순한 동기화
public class SynchronizedSingleton {
private static SynchronizedSingleton instance;
private SynchronizedSingleton() {
// private constructor
}
public static synchronized SynchronizedSingleton getInstance() {
if (instance == null) {
instance = new SynchronizedSingleton();
}
return instance;
}
}
getInstance()
메서드에 동기화를 적용해 스레드 안전성을 보장하지만, 성능 저하 가능성이 존재한다.
Double-Checked Locking
public class DoubleCheckedSingleton {
private static volatile DoubleCheckedSingleton instance;
private DoubleCheckedSingleton() {
// private constructor
}
public static DoubleCheckedSingleton getInstance() {
if (instance == null) {
synchronized (DoubleCheckedSingleton.class) {
if (instance == null) {
instance = new DoubleCheckedSingleton();
}
}
}
return instance;
}
}
volatile
키워드를 사용해 인스턴스의 가시성을 보장하며, 두 번 체크를 통해 동기화의 성능 저하를 최소화한다.
자바 1.5 이전 버전에서는 volatile
키워드가 올바르게 동작하지 않아 컴파일러 최적화나 CPU 캐시로 인해 인스턴스 생성 시 잘못된 참조가 발생할 수 있었다. 이로 인해 Double-Checked Locking 패턴은 안전하지 않았다. 자바 1.5부터는 volatile
의 메모리 가시성 문제와 재정렬 문제를 해결해 해당 패턴이 안전하게 동작하도록 수정되었다.
정적 변수로 들고 있기
public class StaticSingleton {
private static final StaticSingleton INSTANCE = new StaticSingleton();
private StaticSingleton() {
// private constructor
}
public static StaticSingleton getInstance() {
return INSTANCE;
}
}
클래스 로딩 시점에 인스턴스를 생성하므로 스레드 안전하며, 간단한 구현이 가능하다. 다만 인스턴스가 필요하지 않아도 생성된다는 단점이 있다.
Enum 클래스를 싱글턴으로 활용
public enum EnumSingleton {
INSTANCE;
public void doSomething() {
System.out.println("Enum Singleton");
}
}
Enum
을 사용하면 싱글턴을 구현하기 가장 안전한 방법으로, 리플렉션과 직렬화/역직렬화에도 안전하다. 단, Enum 사용이 다소 제한적일 수 있다.
Initialization-on-demand holder idiom
public class HolderSingleton {
private HolderSingleton() {
// private constructor
}
private static class SingletonHolder {
private static final HolderSingleton INSTANCE = new HolderSingleton();
}
public static HolderSingleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
클래스가 로드될 때 내부 SingletonHolder
클래스의 인스턴스가 생성되므로 스레드 안전하며, 게으른 초기화(lazy initialization)를 보장한다.
'스터디' 카테고리의 다른 글
[헤드퍼스트 디자인패턴] 10. 상태 패턴 (0) | 2025.01.15 |
---|---|
헤드퍼스트 디자인패턴 7. 어뎁터 & 퍼사드 패턴 (0) | 2024.12.27 |
헤드퍼스트 디자인패턴 4. 팩토리 패턴 (0) | 2024.12.04 |
헤드퍼스트 디자인패턴 3. 데코레이터 패턴 (0) | 2024.10.22 |
헤드퍼스트 디자인패턴 2. 옵저버 패턴 (0) | 2024.10.09 |
@gmelon :: gmelon's greenhouse
백엔드 개발을 공부하고 있습니다.