from Dictionary - Singleton

Singleton

// Basic
public class Singleton {
    private static Singleton instance;
    
    private Singleton() { }
    
    public static Singleton getInstance() {
        if ( Objects.isNull( instance ) ) { // 쓰레드 동시 접근 시 문제가 발생
            instance = new Singleton(); // 쓰레드 동시 접근 시 여러 번 생성
        }
        
        return instance;
    }
}

// Synchronized
public class Singleton {
    private static Singleton instance;

    private Singleton() { }

    public static synchronized Singleton getInstance() {
        if ( Objects.isNull( instance ) ) { 
            instance = new Singleton(); 
        }

        //인스턴스 생성이 된 이후에도 락을 건다. 불필요!
        return instance;
    }
}

//DCL(Double-Checked-Locking) 
public class Singleton {
    private static Singleton instance;

    private Singleton() { }

    public static Singleton getInstance() {
        if ( Objects.isNull( instance ) ) {
            
            synchronized (Singleton.class) {
                if ( Objects.isNull( instance ) ) {
                    instance = new Singleton();
                    /**
                     * 아래와 같은 재배치가 있을 수 있다.
                     * some_space = allocate space for Singleton Obj;
                     * 
                     *   instancce = some_sapce;
                     * 
                     * create finished
                     */
                }
            }
        }

        //락을 거는 부분을 최소한으로 
        //소스코드 상으로 문제가 없지만 컴파일러에 따라 재배치(reordering) 문제가 발생하기도 한다. 
        return instance;
    }
}

//volatile
public class Singleton {
    
    private volatile static Singleton instance;

    private Singleton() { }

    public static Singleton getInstance() {
        if ( Objects.isNull( instance ) ) {

            synchronized (Singleton.class) {
                if ( Objects.isNull( instance ) ) {
                    instance = new Singleton();
                }
            }
        }

        //문제 없음 
        return instance;
    }
}

//static 초기화 이용
public class Singleton {

    private static Singleton instance;
    
    static {
        instance = new Singleton();  //클래스 로드 시점에 생성해서 하나임을 보장한다.
    }
    
    private Singleton() { }

    public static synchronized Singleton getInstance() {
        return instance;
    }
    
    // 해당 instance를 사용 여부와 상관없이 생성한다. 낭비!
}

//LazyHolder static
public class Singleton {

    private static Singleton instance;
    private Singleton() { }

    public static Singleton getInstance() {
        return LazyHolder.INSTANCE;
    }
    
    private static class LazyHolder {
        private static final Singleton INSTANCE = new Singleton();
    }
    //THREAD-SAFE + LAZY
}