Singleton

μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ΄ μ‹œμž‘λ  λ•Œ μ–΄λ–€ ν΄λž˜μŠ€κ°€ 졜초 ν•œλ²ˆλ§Œ λ©”λͺ¨λ¦¬λ₯Ό ν• λ‹Ήν•˜κ³ (static) κ·Έ λ©”λͺ¨λ¦¬μ— μΈμŠ€ν„΄μŠ€λ₯Ό λ§Œλ“€μ–΄ μ‚¬μš©ν•˜λŠ” λ””μžμΈ νŒ¨ν„΄μ΄λ‹€. μƒμ„±μžκ°€ μ—¬λŸ¬λ²ˆ ν˜ΈμΆœλ˜λ”λΌλ„ μ‹€μ œλ‘œ μƒμ„±λ˜λŠ” κ°μ²΄λŠ” ν•˜λ‚˜μ΄λ©°, 졜초 생성 이후 호좜된 μƒμ„±μžλŠ” μ΅œμ΄ˆμ— μƒμ„±ν•œ 객체λ₯Ό λ°˜ν™˜ν•œλ‹€.

즉, μΈμŠ€ν„΄μŠ€λ₯Ό ν•˜λ‚˜λ§Œ λ§Œλ“€μ–΄ μ‚¬μš©ν•˜κΈ°μœ„ν•œ νŒ¨ν„΄μ΄λ‹€.

ν•˜λ‚˜μ˜ μΈμŠ€ν„΄μŠ€λ§Œμ„ μƒμ„±ν•˜λŠ” μ±…μž„μ΄ 있으며, getInstance() λ©”μ„œλ“œλ₯Ό 톡해 λͺ¨λ“  ν΄λΌμ΄μ–ΈνŠΈμ—κ²Œ λ™μΌν•œ μΈμŠ€ν„΄μŠ€λ₯Ό λ°˜ν™˜ν•˜λŠ” μž‘μ—…μ„ μˆ˜ν–‰ν•œλ‹€.

public class Singleton {
    private static Singleton singletonObject;

    private Singleton() {}

    public static Singleton getInstance() {
        if (singletonObject == null) {
            singletonObject = new Singleton();
        }
        return singletonObject;
    }
}

ν•˜λ‚˜μ˜ μΈμŠ€ν„΄μŠ€λ§Œμ„ μœ μ§€ν•˜κΈ° μœ„ν•΄ μΈμŠ€ν„΄μŠ€ 생성에 νŠΉλ³„ν•œ μ œμ•½μ„ 걸어둬야 ν•œλ‹€. new λ₯Ό μ‹€ν–‰ν•  수 없도둝 μƒμ„±μžμ— private μ ‘κ·Ό μ œμ–΄μžλ₯Ό μ§€μ •ν•˜κ³ , μœ μΌν•œ 단일 객체λ₯Ό λ°˜ν™˜ν•  수 μžˆλ„λ‘ 정적 λ©”μ†Œλ“œλ₯Ό 지원해야 ν•œλ‹€. λ˜ν•œ μœ μΌν•œ 단일 객체λ₯Ό μ°Έμ‘°ν•  정적 μ°Έμ‘°λ³€μˆ˜κ°€ ν•„μš”ν•˜λ‹€.

문제점

λ©€ν‹°μŠ€λ ˆλ”© ν™˜κ²½μ—μ„œ μ‹±κΈ€ν„΄ νŒ¨ν„΄μ„ μ μš©ν•˜λ‹€λ³΄λ©΄ λ¬Έμ œκ°€ λ°œμƒν•  수 μžˆλ‹€. λ™μ‹œμ— μ ‘κ·Όν•˜λ‹€κ°€ ν•˜λ‚˜λ§Œ μƒμ„±λ˜μ–΄μ•Ό ν•˜λŠ” μΈμŠ€ν„΄μŠ€κ°€ 두 개 생성될 수 μžˆλŠ” 것이닀. μ΄λŸ¬ν•œ λ¬Έμ œλŠ” 1. μΈμŠ€ν„΄μŠ€λ₯Ό λ§Œλ“œλŠ” λ©”μ„œλ“œμ— λ™κΈ°ν™”ν•˜λŠ” 방법 (Thread-Safe Initialization) 2. 정적 λ³€μˆ˜μ— μΈμŠ€ν„΄μŠ€λ₯Ό λ§Œλ“€μ–΄ λ°”λ‘œ μ΄ˆκΈ°ν™”ν•˜λŠ” 방법 (Eager Initialization)으둜 ν•΄κ²°ν•  수 μžˆλ‹€.

public class Singleton {
    private static Singleton singletonObject;

    private Singleton() {}

    public static synchronized Singleton getInstance() {
        if (singletonObject == null) {
            singletonObject = new Singleton();
        }
        return singletonObject;
    }
}

λ‹¨μˆœνžˆ synchronized ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•˜λ©΄ μ„±λŠ₯상 μ΄μŠˆκ°€ μžˆμ„ 수 μžˆλ‹€.

public class Singleton {
    private static volatile Singleton singletonObject;

    private Singleton() {}

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

λ‹€μŒκ³Ό 같이 DCL(Double Checking Locking)을 μ¨μ„œ getInstance()μ—μ„œ 동기화 λ˜λŠ” μ˜μ—­μ„ 쀄일 수 μžˆλ‹€. μ΄ˆκΈ°μ— 객체λ₯Ό μƒμ„±ν•˜μ§€ μ•ŠμœΌλ©΄μ„œλ„ λ™κΈ°ν™”ν•˜λŠ” 뢀뢄을 μž‘κ²Œ λ§Œλ“€μ—ˆλ‹€. κ·ΈλŸ¬λ‚˜ 이 μ½”λ“œλŠ” λ©€ν‹°μ½”μ–΄ ν™˜κ²½μ—μ„œ λ™μž‘ν•  λ•Œ, ν•˜λ‚˜μ˜ CPU λ₯Ό μ œμ™Έν•˜κ³ λŠ” λ‹€λ₯Έ CPU κ°€ lock 이 걸리게 λœλ‹€. κ·Έλ ‡κΈ° λ•Œλ¬Έμ— λ‹€λ₯Έ 방법이 ν•„μš”ν•˜λ‹€.

public class Singleton {
    private static volatile Singleton singletonObject = new Singleton();

    private Singleton() {}

    public static Singleton getSingletonObject() {
        return singletonObject;
    }
}

μ •μ λ³€μˆ˜μ— μΈμŠ€ν„΄μŠ€λ₯Ό λ§Œλ“€μ–΄ λ°”λ‘œ μ΄ˆκΈ°ν™” ν•˜λŠ” 방법(Eager initialization)으둜 ν•΄κ²°ν•  수 μžˆλ‹€.

μ™œ 싱글톀을 μ‚¬μš©ν• κΉŒ?

  1. κ³ μ •λœ λ©”λͺ¨λ¦¬ μ˜μ—­μ„ μ‚¬μš©ν•˜λ©΄μ„œ λ©”λͺ¨λ¦¬ λ‚­λΉ„λ₯Ό λ°©μ§€ν•  수 μžˆλ‹€.

  2. μ „μ—­ μΈμŠ€ν„΄μŠ€μ΄κΈ° λ•Œλ¬Έμ— λ‹€λ₯Έ 클래슀의 μΈμŠ€ν„΄μŠ€λ“€μ΄ 데이터λ₯Ό κ³΅μœ ν•˜κΈ° 쉽닀. (Connection Pool, μŠ€λ ˆλ“œ ν’€, λ””λ°”μ΄μŠ€ μ„€μ • 객체처럼 곡톡퇸 객체λ₯Ό μ—¬λŸ¬κ°œ 생성해 μ‚¬μš©ν•΄μ•Όν•˜λŠ” μƒν™©μ—μ„œ 많이 μ‚¬μš©)

  3. 두 번째 μ΄μš©μ‹œλΆ€ν„°λŠ” 객체 λ‘œλ”© μ‹œκ°„μ΄ 쀄어 μ„±λŠ₯이 μ’‹μ•„μ§„λ‹€.

μ°Έμ‘° νŽ˜μ΄μ§€

Last updated

Was this helpful?