ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Design Pattern] Singleton Pattern 싱글톤 패턴
    Study/Design Pattern 2021. 7. 15. 19:16

    싱글턴 패턴이란(Singleton Pattern) 어떤 구현 클래스의 인스턴스를 단 1개만 생성하는 패턴입니다. 인스턴스가 남용돼서  자원을 낭비하는 경우를 없애고, 시스템 전반에 걸쳐 하나의 자원을 공유하여 사용하고자 할때 유용한 패턴입니다.

     

    그래서 싱글톤 패턴을 간단하게 구현해보면 아래와 같이 구현 가능합니다. 기본생성자, 복사생성자, 제거자를 private으로 지정하여 외부의 접근을 막고, getInstance 맴버함수로만 instance를 생성할 수 있게 하는 것입니다.

     
     
     

     

    public class SingleTon{
    
       private static SingleTon instance = null;
       private SingleTon(){}
    
       public static SingleTon getInstance(){
            if(instance==null){
                instance = new SingleTon();
            }
            return instance;
       }
    }

     

    단 위 같은 코드는 문제가 있습니다. 만약 다중 쓰레딩 환경이면 getInstance 메소드를 통해 instance를 가져오는 것이 thread-safe 하지 않을 수 있습니다. 만약 instance = null인 상황에서, 2개의 thread가 동시에 getInstance 메소드를 호출하면 각각 new 연산자로 할당받을 수 있을 수 있기 때문입니다.

    이를 해결하기 위해 synchronized 키워드를 이용할 수 있습니다. 아래처럼 getInstance 메소드 앞에 synchronized 키워드를 붙이게 되면 thread-safe하게 동작합니다.

     
     
     
    public class SingleTon{
    
       private static SingleTon instance = null;
       private SingleTon(){}
    
       public static synchronized SingleTon getInstance(){
            if(instance==null){
                instance = new SingleTon();
            }
            return instance;
       }
    }​

     

    위 방법은 확실히 thread-safe합니다. 하지만 치명적인 단점이 존재합니다. 바로 인스턴스를 호출하기 위해서는 항상 동기화 블록을 지나게 됩니다. synchronized 키워드는 성능을 엄청 떨어트리는 단점이 있으므로 성능까지 고려해야 하는 상황이면 좋지 않은 방법이 돼버립니다.

     

     

    그래서 이럴 때는 Double Checking Locking (DCL) 방법을 사용하면 됩니다.  동기화 블록에 들어가기 전에 instance의 생성 여부를 확인해 주고 진입합니다. 그리고 동기화 블록에 진입하자마자 다시 한번 더 검사해 주는 방법입니다. 이때 instance 변수가 volatile 키워드로 선언되어 있는 것을 확인할 수 있는데, votaile로 선언하면 변수에 접근할 때 캐시를 참조하지않고 항상 메모리를 참조하게 됩니다. 그래서 쓰레드간 캐시가 달라 생기는 문제를 방지할 수 있습니다. 

    public class SingleTon{
    
       private volatile static SingleTon instance = null;
       private SingleTon(){}
    
       public static SingleTon getInstance(){
            if(instance==null){
                synchronized(SingleTon.class){
                    if(instance==null){
                        instance = new SingleTon();
                    }
                }
            }
            return instance;
       }
    }
     
     
     
     
     
     
     
     
     

    댓글

Designed by Tistory.