Singleton은 유일한 Instance를 만들어 사용하는 방법이다.
생성자를 private으로 하여 다른 곳에서 Instance를 직접 생성할 수 없으며, public getInstance()
를 통해서만 instance를 가져가서 사용할 수 있다.
- 객체 = Object = Compile된 각각의 .class file
- 개체 = Instance = Compile된 .class file을 new 연산자를 사용하여 Memory에 Loading한 상태
기본적으로는 이런 느낌이다.
|
|
필요성
설정 파일 등 여러 개가 있으면 혼란스러울 수 있는 경우 Singleton을 통해 하나의 자원만 사용할 수 있게 한다.
전역적으로 접근이 가능해야 하지만 단 하나만 있어야 한다.
전역 변수는 여러 개가 생성될 수 있기 때문에 Singleton을 사용하는 것이다.
싱글턴 패턴은 해당 클래스의 인스턴스가 하나만 만들어지고, 어디서든지 그 인스턴스에 접근할 수 있도록 하기 위한 패턴입니다. - Head First Design Patterns
또한, Global Class는 어플리케이션이 시작될 때 항상 로딩되지만 Singleton Class는 시작되는 지점을 개발자가 지정할 수 있다.
Trouble shooting
MultiThreading 문제 해결
위쪽에서 표현한 코드는 MultiThread 환경
에서 추가적인 Instance의 생성
을 완전히 방어할 수 없다.
고로, Thread 사용 시 기본적인 방어 방법인 Syncronized
를 붙여보기로 한다.
|
|
Synchronized로 인한 성능 문제 해결
Synchronized로 인한 MultiThreading 시의 성능은 엄청나게 떨어진다.
고로, Instance를 미리 생성
해 보도록 한다.
|
|
문제를 해결하는 또 다른 방법
DCL (Double-Checking Locking) 이라는 방법으로 Instance가 생성되었으면 그냥 넘기고, 없는 경우에만 synchronized 를 걸어주어 Instance를 요청하는 Thread들에 부담을 덜어주는 방법이다.
volatile
keyword는 Java 코드의 변수(Variable)를 메모리에 저장(Store)
하라는 의미이다. volatile 변수
는 CPU cache를 사용하지 않고 Main memory에 직접 read/write 한다.
volatile
에 대한 자세한 내용은 여기를 참조해 보자.
결론적으로 여기서는 CPU Cache를 통할 때 변수의 무결성을 보장할 수 없으므로 volatile
을 통해 Main memory에 직접 접근하겠다는 뜻이다.
|
|
마무리
- 무분별하게 리팩토링 하겠다고 Singleton 남발하지 말 것.
- 전역 설정이 필요할 때 등 꼭 필요할 때만 사용할 것.
- 위에서 나열한 방법들 중 해당 어플리케이션에 적절한 것을 사용할 것. 단일 Thread를 사용하는 프로그램에서 굳이 synchronized로 성능 저하를 시킬 필요는 없다.
출처
- http://noesse.tistory.com/28
- Head First Design Patterns - 한빛미디어, O’Reilly.