프로그램 아키텍쳐/디자인패턴

싱글턴 패턴 ( Singleton Pattern )

본클라쓰 2009. 1. 5. 19:25

 

싱글턴 패턴은 특정 클래스에 대해 인스턴스가 하나만 생성되고, 어디에서든지 그 인스턴스에 접근할 수 있도록 하기 위한 패턴이다. 예를 들면, 레지스트리 설정을 처리하는 객체, 로그 기록용 객체, 프린터나 그래픽 카드 같은 디바이스를 위한 디바이스 드라이버 같은 것을 들 수 있다. 싱글턴 패턴은 정적(static) 클래스 변수와 메소드를 사용하고 접근 제한자(Access Modifier)를 사용하여 구현한다.

 

 

다음 코드는 고전적인 싱글턴 패턴입니다. 

public class Singleton {

 

    privatestatic Singleton instance;    /* 유일한 인스턴를 저장하기 위한 변수 */

 

     /* 생성자를 private로 생성하여 이 클래스에서만 인스턴스를 생성할 수 있음 */

    privateSingleton() {};

 

    /* getInstance메소드를 정적 메소드로 선언하여 인스턴스를 생성해 리턴 */

    public static Singleton getInstance() {      

        /* 인스턴스가 없다면 객체를 생성, 있다면 그 객체를 리턴 */ 

        if( instance == null ) { instance = new Singleton(); }    

        return instance;

    }

}

 

 하지만 이런 방식으로 싱글턴 패턴을 구현하면 멀티 쓰레드 환경에서는 객체가 한개 이상 생성 될 수 있다. 멀티 쓰레드 환경에서 객체가 한개 이상 생성되는 것을 방지 하기 위해서 동기화(Synchronized)를 사용한다. 다음 동기화를 사용한 싱글턴 패턴이다.

 

public class Singleton {

 

    privatestatic Singleton instance;   

 

    private Singleton() {}; 

 

    /* synchronized 키워드를 사용하여 멀티 쓰레드시 동시 실행을 방지  */

    public static synchronized Singleton getInstance() {      

        if( instance == null ) { instance = new Singleton(); }    

        return instance;

    }

}   

 

 하지만 동기화방식을 사용하면 불필요한 오버헤드만 증가시키는 단점이 있다. 그렇다면 더 효율적인 방법이 없는가? 해결책은 인스턴스를 필요할 때 생성하지 말고, 처음부터 만들어 버리면 된다.  

 

public class Singleton {

 

    private static Singleton instance = new Singleton();

 

    private Singleton() {};

 

    public static Singleton getInstance() { 

        return instance;

    } 

}

 초기화 부분에서 바로 인스턴스를 생성합니다. 그럼 쓰레드를 써도 문제가 없습니다.

 

 또 다른 멀티 쓰레드 문제를 해결하는 방법은 DCL(Double-cheking Locking)을 써서 getInstance()에서 동기화 되는 부분을 줄인다.

 

public class Singleton {

 

    private volatile static Singleton instance;

 

    private Singleton() {};

 

    public static Singleton getInstance() {

 

        if( instance == null ) {   /* 인스턴스가 있는 확인하고, 없으면 동기화 블럭으로 들어감 */

 

            synchronized (Singleton.class) {    /* 동기화 */

                if( instance == null ) {     /* 다시한번 null인지 확인하고 인스턴스를 생성함 */

                    instance = new Singleton();

               }    

            }

 

       }

       return instance;

}