ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Singleton 구현 기법
    JAVA 2023. 8. 27. 20:18

    Singleton 패턴

    생성자가 여러 차례 호출되더라도 실제로 생성되는 객체는 하나이고 최초 생성 이후에 호출된 생성자는 최초의 생성자가 생성한 객체를 리턴한다.

     

    기본적인 Singleton 패턴

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

    Singleton의 getInstance를 호출할때 instance가 없다면 만들어주고 있다면 만들어둔 instance를 return 해준다. 이 코드는 스레드가 여러개일때 문제가 생길 수 있다. Tread A 와 Thread B가 동시에 instance == null 을 최초 검사한다면 두 스레드에서 instance를 각각 생성하여 instance가 두개가 될 수 있다.

     

    synchronized를 이용한 패턴

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

    위의 기본적인 패턴의 문제점을 해결하기 위해 synchronized 키워드를 넣었다. 이 경우 instance 생성은 스레드가 여러개이더라도 한번만 생성된다. 하지만 getInstance를 할때마다 불필요한 lock이 걸려 성능상 문제가 있을 수 있다.

     

    DCL (Double Checked Locking) 패턴

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

    위 synchroinzed 패턴의 성능을 향상시키기 위해 생성해주는 부분만 synchronized block 으로 실행시켜준다.

     

    static 초기화를 이용한 패턴

    public class Singleton {
    
    	private static Singleton instance = new Singleton();
    	
    	private Singleton(){}
    	
    	public static Singleton getInstance() {
    		return instance;
    	}
    	
    }

    최초 instance 생성을 getInstance 호출 시점이 아닌 클래스 가 로딩되는 시점에 생성해주는 방식이다. 간결하고 Thread-safe하다. 하지만 사용할지 안할지 모르는 instance를 미리 만들어두는것이 옳은것인가에 대한 문제가 있다. 

     

    LazyHolder 패턴

    public class Singleton {
    	private Singleton(){}
    
    	public static Singleton getInstance() {
    		return LazyHolder.INSTANCE;
    	}
    
    	private static class LazyHolder {
    		private static final Singleton INSTANCE = new Singleton();
    	}
    }

    이 방법은 static 영역에서 초기화를 하지만 실제 getInstance로 LazyHolder를 참조할때 class가 로딩되며 초기화가 진행된다. 

     

    참조

    https://javaplant.tistory.com/21

    'JAVA' 카테고리의 다른 글

    Java Generic Compile 동작  (0) 2023.09.11
    JVM Memory Area  (0) 2023.09.08
    Java 버전 별 ArrayList add 동작  (0) 2023.09.06
    Java Thread Safety 한 개발  (0) 2023.08.29
    Transaction 격리 레벨 / 전파 모델  (0) 2023.08.06
Designed by Tistory.