본문 바로가기

Programming/Java

Java Singleton Pattern

오늘은 Singleton Pattern 에 대해서 글을 적으려고 해요.


한국어로는 싱글턴 패턴이라고 하는데, 저는 원문을 살려서 의미가 명확하게 드러나도록 할게요.


Singleton pattern 은 유일무이한 객체를 만들어 내는 패턴 이라고 보면 됩니다.

객체를 반드시 한개만 생성 해야만 하는 곳에서 사용이 됩니다.

예를 들어, Device Driver, Thread Pool 같은 것들에서 사용이 됩니다.


내용은 쉽지만, Singleton 을 재대로 구현 하려면 상당한 지식이 필요하다고 생각합니다.


Singleton 을 생성하는 방법은 대표적으로 4가지 방법이 있습니다.


1. Lazy Instantiation

2. synchronize 를 하는 방법

3. DCL(Double Checking Lock) 을 이용하는 방법

4. 처음부터 객체를 생성해서 사용하는 방법


1. Lazy Instantiation 부터 간단한 예를 들어서 살펴보도록 하죠.

public class Singleton{

private static Singleton instance;


private Singleton(){}


public static Singleton getInstance(){

if(instance == null)

instance = new Singleton();

return instance;

}

}

여기서 Lazy Instantiation 이라고 하는 이유는, instance 가 있는지 없는지 먼저 체크를 하고, 객체가 있으면 그냥 리턴하고, 없으면 생성해서 리턴하기 때문입니다.

이렇게 해서 Singleton 객체를 만들면 문제가 생길 수 있습니다. 바로 Multithreading 상황에서

객체가 교묘한 타이밍에 체크를 벗어나면, 객체가 2개 이상이 생길 수가 있죠. ^^

그래서 보통 이 방법은 사용하지 않습니다. 그래서 이것의 대안책으로 synchronize 하는 방법이 있는데, 이것은 확실하게 객체를 1개 생성하는 것을 보장 해줍니다. 하지만, 보통 실행속도가 100배 정도 느리다고 생각하시면 됩니다. 그래서 속도가 중요한 프로그램에서는 사용하면 안되겠죠.


2. synchronize pattern


public class Singleton{

private static Singleton instance;


private Singleton(){}


public static synchronized Singleton getInstance(){

if(instance == null)

instance = new Singleton();

return instance;

}

}

위의 소스처럼 간단하게 sychronized 라는 키워드만 붙여주면 끝입니다.


3. DCL(Double Checking Locking) Pattern

public class Singleton{

private volatile static Singleton instance;


private Singleton(){}


public static Singleton getInstance(){

if(instance == null){ // 인스턴스가 없으면, 동기화 블럭으로 이동

synchronized(Singleton.class){//처음에만 동기화가 되게 함.

if(instance == null)// volatile keyword를 이용한 초기화 과정이 정확하게

instance = new Singleton();// 되는 것을 보장.

}

}

return instance;

}

}

DCL 은 JRE 1.5 이상에서 써야 재대로 작동한다는 언급이 Sun 공식 문서에 나와있네요 ^^


4. 처음부터 객체를 생성해서 만드는 법.


public class Singleton{

private static Singleton instance = new Singleton();


private Singleton(){}


public static Singleton getInstance(){

return instance;

}

}

이렇게 하면 처음부터 객체가 생성되서 객체가 2개이상이 만들어질 일은 없겠죠?

하지만 메모리를 많이 사용하는 객체라면 사용을 고려해 볼 필요도 있겠죠?