[디자인 패턴] 싱글턴 패턴(Singleton Pattern) By starseat 2023-08-14 16:16:38 알고리즘 Post Tags # 싱글턴 패턴 - **클래스 인스턴스를 하나만 만들고, 그 인스턴스로의 전역 접근을 제공한다.** - 하나뿐인 인스턴스를 관리하도록 만든다. - 다른 어떤 클래스에서도 자신의 인스턴스를 추가로 만들지 못하게 해야 한다. - 인스턴스에 접근할 수 있도록 전역 접근 지점을 제공한다. # 고전적인 싱글턴 패턴 구현 법 ```java public class SingletonExample { // 하나뿐인 인스턴스를 저장하는 정적 변수 private static SingletonExample instance; // 생성자를 private 으로 선언해서 다른 클래스로의 생성 방지 private SingletonExample() { } public static SingletonExample getInstance() { if(instance == null) { instance = new SingletonExample(); } return instance; } // ... } ``` # 멀티스레딩 문제 위의 **고전적인 싱글턴 패턴 구현 법** 은 멀티스레딩 환경에서 취약한 부분이 있다. 상태 체크를 하여 후 처리를 하는 객체일 경우 상태 체크 전 후 처리를 하게 될 수 있다. # 멀티 스레딩 문제 해결하기 `getInstance()` 메소드에 `synchronized` 키워드 붙이기.(쓰레드 동기화) ```java public class SingletonExample { private static SingletonExample instance; private SingletonExample() { } public static synchronized SingletonExample getInstance() { if(instance == null) { instance = new SingletonExample(); } return instance; } // ... } ``` # 더 효율적으로 멀티 스레딩 문제 해결하기 ## 방법 1 - 속도가 중요하지 않다면 그냥 두기 `synchronized` 키워드로 속도 문제가 생길 수 있지만 (**약 100배 정도 성능 저하**) 속도가 그리 중요하지 않다면 그냥 두자. ## 방법 2 - 처음부터 인스턴스 만들기 인스턴스가 필요할 때 생성하지 말고, 정적 초기화(static initializer) 하기. ```java public class SingletonExample { // 정적 초기화 private static SingletonExample instance = new SingleExample(); private SingletonExample() { } public static synchronized SingletonExample getInstance() { // 인스턴스가 이미 있으니 바로 반환 return instance; } // ... } ``` 이 방법을 사용하면 클래스가 로딩될 때 JVM 에서 SingletonExample 의 하나 뿐인 인스턴스를 생성해 준다. JVM 에서 하나 뿐인 인스턴스를 생성하기 전까지 그 어떤 쓰레드도 `instance` 정적 변수에 접근 할 수 없다. ## 방법 3 - DCL 을 사용하여 동기화되는 부분 줄이기 **DCL(Double-Checked Locking)** 을 사용하면 인스턴스가 생성되어 있는지 확인한 다음 생성되어 있지 않았을 때만 동기화 할 수 있다. 이러면 처음에만 동기화 하고 나중에는 동기화 하지 않아도 된다. (`volatile` 키워드를 사용) 단, **DCL 은 java 1.4 이전 버전에서는 사용할 수 없다. (1.5 이상 버전에서 사용)** - `volatile` 키워드를 사용하면 멀티쓰레딩을 사용하더라도 `instance` 변수가 `SingletonExample` 인스턴스로 초기화되는 과정이 올바르게 진행된다. ```java public class SingletonExample { private volatile static SingletonExample instance; private SingletonExample() { } public static synchronized SingletonExample getInstance() { // 인스턴스를 확인하고 없으면 동기화된 블록 진입 if(instance == null) { // 이러면 처음에만 동기화됨. synchronized (SingletonExample.class) { // 한번 더 null 체크 후 인스턴스 생성 if(instance == null) { instance = new SingletonExample(); } } } return instance; } // ... } ``` # 참조 - [헤드 퍼스트 디자인 패턴](https://product.kyobobook.co.kr/detail/S000001810483) Previous Post [디자인 패턴] 팩토리 패턴(Factory Pattern) Next Post -