싱글턴 패턴이란?
"클래스 인스턴스를 하나만 만들고, 그 인스턴스로의 전역 접근을 제공한다."
말 그대로 하나의 클래스로 하나의 객체만 만들겠다는 이야기다.
이해를 돕기위해 코드를 살펴보자. 아래는 고전적인 싱글턴 패턴을 구현한 것이다.
public class Singleton {
private static Singleton uniqueInstance;
private Singleton(){}
public static Singleton getInstance(){
if(uniqueInstance == null){
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
}
자 생성자(Singleton)에 주목해보자.
private으로 선언함으로써 이 클래스 외에서는 접근이 불가능하다. 즉, new Singleton() 으로 객체 생성이 불가능해진다.
그래서 getInstance() 메소드를 통해 static 변수 uniqueInstance에 값이 없으면 객체를 생성해주고, 값이 있으면 그 값을 반환하게 끔 해준다. 이러면 단 Singleton 객체는 단 하나만 존재할 수 밖에 없게 되는 것이다.
그런데 위 코드는 멀티 스레딩 시에 문제점이 생긴다. if(uniqueInstance == null) 이 부분에서 각각의 스레드가 true 값을 가지기 때문에 두 개의 스레드에서 각각 객체 생성이 일어난다. 즉, 두 번 이상 객체가 생성되어 싱글턴 패턴에 위반하게 된다.
그러면 어떻게 해결할까? 다양한 방법이 있다. 한 번 살펴보자.
프로그램 시작 시, 인스턴스 생성하기
public class Singleton {
private static Singleton uniqueInstance = new Singleton();
private Singleton(){
}
public static Singleton getInstance(){
return uniqueInstance;
}
}
- 처음부터 Singleton2 인스턴스를 만들어보자. 정적 초기화 부분에서 싱글턴 패턴을 생성하면서 스레드를 사용해도 아무 문제 없이 작동하는 것을 확인할 수 있을 것이다.
DCL (Double Checking Locking)
public class Singleton {
private volatile static Singleton instance = null;
private Singleton() {
}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class){
if(instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
- 인스턴스가 생성되어 있는지 확인 후, 생성되어 있지 않았을 때만 동기화를 시킴
- volatile
-> 변수를 CPU cache에 저장하지 않고 메모리에서 읽고 저장한다.
-> 스레드를 사용할 때 다른 프로세서에 있는 cache에 변수값이 저장되어 서로 다른 값을 사용하는 것을 방지한다.
- synchronized
-> 여러 스레드에서 사용하려고 할 때 locking 매커니즘을 제공하여 한 번에 한 개 스레드만 사용할 수 있도록 한다.
inner static class 사용
public class Singleton {
private static class InnerSingleton{
static final Singleton instance = new Singleton();
}
private Singleton() {
System.out.println("Singleton constructor");
}
public static Singleton getInstance() {
return InnerSingleton.instance;
}
public void print() {
System.out.println("Singleton instance hashCode = " + InnerSingleton.instance.hashCode());
}
}
- 내부 정적 클래스를 사용하면 JVM에서는 해당 싱글턴 클래스를 메모리에 load할 때, 정적 멤버 변수가 없으므로 싱글턴 인스턴스를 생성하지 않는다.
enum
자 이제까지 싱글턴 패턴의 원리를 알아봤다. 근데 사실 enum 키워드로 모든 것이 해결된다.
public enum Singleton3{
UNIQUE_INSTANCE;
}
...
'디자인 패턴' 카테고리의 다른 글
[디자인 패턴] Adapter Pattern (0) | 2023.12.09 |
---|---|
[디자인 패턴] 컴포지트 패턴 (Composite Pattern) (0) | 2023.12.09 |
[디자인 패턴 기초] 빌더 패턴 (Builder Pattern) (0) | 2023.10.17 |
[디자인 패턴 기초] 데코레이터 패턴 (Decorator Pattern) (1) | 2023.10.10 |
[디자인 패턴 기초] 옵저버 패턴(observer pattern) (0) | 2023.09.26 |