싱글턴 패턴의 정의
- 싱글턴 패턴(Singleton Pattern)은 클래스 인스턴스를 하나만 만들고, 그 인스턴스로의 전역 접근을 제공합니다
- 싱글턴 패턴을 실제로 적용할 때는 클래스에서 하나뿐인 인스턴스를 관리하도록 만들면 됩니다. 그리고 어떤 클래스에서도 자신의 인스턴스를 추가로 만들지 못하게 해야 합니다. 인스턴스가 필요하다면 반드시 클래스 자신을 거치도록 해야겠죠.
- 어디서든 그 인스턴스에 접근할 수 있도록 전역 접근 지점을 제공합니다. 언제든 이 인스턴스가 필요하면 클래스에 요청할 수 있게 만들어 놓고, 요청이 들어오면 그 하나뿐인 인스턴스를 건네주도록 만들어야 하죠. 앞에서 이미 봤듯이, 싱글턴이 게으른 방식으로 생성되도록 구현할 수도 있습니다. 특히 자원을 많이 잡아먹는 인스턴스가 있다면 이런 기법이 괘 유용하죠
멀티스레딩 문제 해결하기
→ 동기화
- 동기화가 꼭 필요한 시점은 이 메소드가 시작되는 때뿐. 바꿔 말하면, 일단 uniqueInstance 변수에 singleton 인스턴스를 대입하면 굳이 이 메소드를 동기화된 상태로 유지할 필요가 없습니다. 처음을 제외하면 동기화는 불필요한 오버헤드만 증가시킬 뿐입니다.
더 효율적으로 멀티스레딩 문제 해결하기
- 대부분의 자바 어플리케이션을 지원하려면 멀티스레드 환경에서도 싱글턴이 돌아가도록 만들어야 함. 하지만 getInstance() 메소드를 동기화하면 적지 않은 대가를 치러야 함. 다른 방법은?
- 방법1. 속도가 그리 중요하지 않다면 그냥 두기
- getInstance() 메소드가 애플리케이션에 큰 부담을 주지 않는다면 그냥 둬도 됩니다. 동기화하는 게 그리 어려운 일도 아니고, 효율도 좋을 수 있습니다. 다만 메소드를 동기화하면 성능이 100배 정도 저하된다는 사실만은 기억해둡시다. 만약 getInstance()가 애플리케이션에서 병목으로 작용한다면 다른 방법을 생각해봐야 합니다.
- 방법2. 인스턴스가 필요할 때는 생성하지 말고 처음부터 만듭니다.
- 정적 초기화부분(static initializer)에서 Singleton의 인스턴스를 생성합니다. 이러면 스레드를 써도 별 문제가 없습니다.
- 방법3. DCL을 써서 getInstance()에서 동기화되는 부분을 줄입니다.
- DCL(Double-Checked Locking)을 사용하면 인스턴스가 생성되어 있는지 확인한 다음 생성되어 있지 않았을 때만 동기화할 수 있습니다. 이러면 처음에만 동기화하고 나중에는 동기화하지 않아도 됩니다.
- 동기화 문제, 클래스 로딩 문제, 리플렉션, 직렬화와 역직렬화 문제 등은 enum으로 싱글턴을 생성해서 해결할 수 있음
summary
- 어떤 클래스에 싱글턴 패턴을 적용하면 그 클래스의 인스턴스가 1개만 있도록 할 수 있습니다.
- 싱글턴 패턴을 사용하면 하나뿐인 인스턴스를 어디서든지 접근할 수 있도록 할 수 있습니다.
- 자바에서 싱글턴 패턴을 구현할 때는 private 생성자와 정적 메소드, 정적 변수를 사용합니다.