
싱글톤 패턴(Singleton Pattern)의 용도
스레드 풀, 캐시, 대화상자, 사용자 설정 혹은 레지스트리를 처리하는 객체, 로그 기록용 객체, 디바이스 드라이버 등 객체 중에 하나만 있으면 되는 경우 사용합니다.
고전적인 싱글톤 패턴(Singleton Pattern)
고전적인 싱글톤 패턴 방식은 아래와 같습니다.
생성자는 private
으로 설정하고, 객체를 부를 때에는 따로 static
함수를 사용합니다. 인스턴스가 있을 경우에는 그대로 그 인스턴스를 반환하고, 인스턴스가 없을 경우에는 생성하여 인스턴스를 반환하변 됩니다.
public class Singleton {
private static Singleton uniqueInstance;
private Singleton() {}
public static Singleton getInstance() {
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
}
싱글톤 패턴(Singleton Pattern)의 정의
싱글톤 패턴
싱글톤 패턴은 해당 클래스의 인스턴스가 하나만 만들어지고, 어디서든지 그 인스턴스에 접근할 수 있도록 하기 위한 패턴입니다.
- 반드시 생성은 클래스 자신을 통해 하도록 하여, 다른 어떤 클래스에서도 자신의 인스턴스를 추가로 만들지 못하도록 합니다.
- 싱글톤은 '게으르게' 생성할 수 있습니다. 클래스의 객체가 자원을 많이 잡아먹는 경우에 유용합니다.
멀티스레딩 문제 해결 방법
간단한 해결 방법
객체를 부르는 getInstance()
함수를 동기화시키면 해결할 수 있습니다.
public class Singleton {
private static Singleton uniqueInstance;
private Singleton() {}
public static synchronized Singleton getInstance() {
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
}
하지만, 위의 방법은 동기화가 좀 아깝게 느껴질 수 있습니다. 왜냐하면 꼭 필요한 시점이 메소드를 시작할 때 뿐이기 때문입니다. Head First Design Patterns에서는 아래와 같이 해결 방법을 제시합니다.
getInstance()
의 속도가 그리 중요하지 않다면 그냥 둡니다.- 인스턴스를 필요할 때 생성하지 말고, 처음부터 만들어 버립니다.
public class SingletonNoSynchronized { private static final SingletonNoSynchronized uniqueInstance = new SingletonNoSynchronized(); private SingletonNoSynchronized() { } private static SingletonNoSynchronized getInstance() { return uniqueInstance; } }
- DCL(Double-checking Locking)을 써서
getInstance()
의 동기화 부분을 줄입니다.public class DoubleCheckLock { private volatile static DoubleCheckLock uniqueInstance; private DoubleCheckLock() {} public static DoubleCheckLock getInstance() { if (uniqueInstance == null) { synchronized (DoubleCheckLock.class) { if (uniqueInstance == null) { return new DoubleCheckLock(); } } } return uniqueInstance; } }
volatile
을 사용하는 이유는 reference를 읽어보는 것이 좋을 것 같습니다.
추가 정보
- 클래스 로더가 두 개 이상이라면 같은 클래스를 여러 번 로딩할 수도 있습니다. 클래스 로더를 여러 개 사용한다면 싱글턴 패턴 사용을 조심해야 합니다. 클래스 로더를 직접 지정해서 이 문제를 피할 수 있습니다.
- 책에서는 다루지 않고 있지만 싱글톤 패턴을 구현하기 위해
Lazy Holder
라는 방식이 있으니 참고하시면 좋습니다.
반응형
'Design Patterns' 카테고리의 다른 글
Head First Design Patterns 7. Facade Pattern (0) | 2022.02.26 |
---|---|
Head First Design Patterns 6. Command Pattern (0) | 2022.02.25 |
Head First Design Patterns 4. Factory Pattern (0) | 2022.02.19 |
Head First Design Patterns 3. Decorator Pattern (0) | 2022.02.13 |
Head First Design Patterns 2. Observer Pattern (0) | 2022.02.06 |