ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Java] λ””μžμΈ νŒ¨ν„΄ (Singleton νŒ¨ν„΄)
    Android/Java 2021. 1. 5. 22:50
    λ°˜μ‘ν˜•
    • 이 글은 "μΈν”„λŸ° Java λ””μžμΈ νŒ¨ν„΄" κ°•μ˜λ₯Ό λ“£κ³  κ³΅λΆ€ν•œ λ‚΄μš©μ„ λ°”νƒ•μœΌλ‘œ 글을 μž‘μ„±ν•˜μ˜€μŠ΅λ‹ˆλ‹€.

    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 λ©”μ†Œλ“œλ₯Ό static으둜 κ΅¬ν˜„ν•˜μ—¬ 객체 생성을 ν•˜μ§€ μ•Šμ•„λ„ ν˜ΈμΆœν•  수 μžˆλ„λ‘ ν•©λ‹ˆλ‹€.

    public class Main {
        public static void main(String[] args) {
    
            Singleton singleton = Singleton.getInstance();
            Singleton singleton1 = Singleton.getInstance();
    
            if(singleton == singleton1){
                System.out.println("κ°™μŒ");
            }else{
                System.out.println("닀름");
            }
    
        }
    }
    • new 둜 객체 μƒμ„±ν•˜λŠ” 것을 막기 μœ„ν•΄μ„œ Singleton κ°μ²΄μ—μ„œλŠ” μƒμ„±μžλ₯Ό μ œν•œμ ‘κ·Όμžλ₯Ό μ‚¬μš©ν•΄μ•Ό ν•©λ‹ˆλ‹€.

    • Mainν•¨μˆ˜λ₯Ό μ‹€ν–‰ν•œ κ²°κ³ΌλŠ” 두 μΈμŠ€ν„΄μŠ€ λͺ¨λ‘ 같은 μΈμŠ€ν„΄μŠ€μΈ 것을 확인할 수 μžˆμŠ΅λ‹ˆλ‹€.


    Sigleton 동기화

    μ—¬λŸ¬ μ“°λ ˆλ“œμ—μ„œ μœ„ 클래슀의 getInstance λ©”μ†Œλ“œλ₯Ό ν˜ΈμΆœν•˜κ²Œ 되면 λ™μ‹œμ— μž‘μ—…μ„ ν•˜κΈ° λ•Œλ¬Έμ— instanceλŠ” null둜 νŒλ‹¨ν•˜μ—¬ μ“°λ ˆλ“œμ—μ„œ ν˜ΈμΆœν•œ 만큼 μΈμŠ€ν„΄μŠ€κ°€ 생성할 κ²ƒμž…λ‹ˆλ‹€. 이λ₯Ό λ°©μ§€ν•˜κΈ° μœ„ν•΄ μΈμŠ€ν„΄μŠ€ 생성 μ „ ν•œλ²ˆ 더 ν™•μΈν•˜λŠ” 방법을 μ‚¬μš©ν•˜λŠ”λ° μ“°λ ˆλ“œκ°€ λ™μ‹œμ— μ ‘κ·Όν•˜μ§€ λͺ»ν•˜λ„둝 두 번째 ν™•μΈν•˜κΈ° 전에 락을 κ±Έμ–΄μ£ΌλŠ” 것이 일반적이라고 ν•©λ‹ˆλ‹€.


    1. Thread safe Lazy initialization

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

    λ©”μ†Œλ“œ 전체에 μž„κ³„μ˜μ—­μœΌλ‘œ μ„€μ •ν•˜μ—¬ synchronizedλ₯Ό μΆ”κ°€ν•˜λŠ” 것은 비ꡐ적 큰 μ„±λŠ₯μ €ν•˜κ°€ λ°œμƒν•˜κΈ° λ•Œλ¬Έμ— ꢌμž₯ν•˜λŠ” 방법은 μ•„λ‹ˆλΌκ³  ν•©λ‹ˆλ‹€.

    2. Thread safe Lazy initialization + Double-checked locking

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

    동기화 λΈ”λŸ­ 내뢀에 μΈμŠ€ν„΄μŠ€ μ—¬λΆ€λ₯Ό ν™•μΈν•œ ν›„ μƒμ„±ν•˜κ²Œ 되면 getInstanceλ₯Ό ν˜ΈμΆœν•  λ•Œλ§ˆλ‹€ synchronziedλ₯Ό μ‚¬μš©ν•˜κΈ° λ•Œλ¬Έμ— μ„±λŠ₯ μ €ν•˜λŠ” λΆˆκ°€ν”Όν•©λ‹ˆλ‹€. λ¨Όμ € μΈμŠ€ν„΄μŠ€ μ—¬λΆ€λ₯Ό ν™•μΈν•˜κ³  두 번째 μΈμŠ€ν„΄μŠ€ μ—¬λΆ€ 확인 전에 동기화λ₯Ό ν•˜κ²Œ 되면 thread-safe ν•˜λ©΄μ„œλ„ 처음 생성 μ΄ν›„μ—λŠ” synchronized λΈ”λŸ­μ„ κ±°μΉ˜μ§€ μ•ŠκΈ° 떄문에 μ„±λŠ₯ μ €ν•˜λ₯Ό μ™„ν™”ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

    3. Initialization on demand holder idiom (holder에 μ˜ν•œ μ΄ˆκΈ°ν™”)

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

    κ°œλ°œμžκ°€ 직접 동기화 문제λ₯Ό ν•΄κ²°ν•˜κΈ°λž€ 쉽지 μ•ŠμŠ΅λ‹ˆλ‹€. 이λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•΄μ„œλŠ” λ§Žμ€ μ˜ˆμ™Έμ²˜λ¦¬μ™€ ꡬ쑰 κ°œμ„ λ“€λ‘œ 인해 λ³΅μž‘ν•΄μ§€κ³  λΉ„μš©μ΄ 컀질 수 μžˆμŠ΅λ‹ˆλ‹€. λ§ˆμ§€λ§‰ 방법은 JVM의 클래슀 μ΄ˆκΈ°ν™” κ³Όμ •μ—μ„œ 보μž₯λ˜λŠ” μ›μžμ  νŠΉμ„±μ„ μ΄μš©ν•˜μ—¬ μ‹±κΈ€ν„΄μ˜ μ΄ˆκΈ°ν™” 문제λ₯Ό JVMμ—κ²Œ μ±…μž„μ„ λ„˜κΈΈ 수 μžˆμŠ΅λ‹ˆλ‹€.Holder 클래슀 μ•ˆμ— μ„ μ–Έλœ μΈμŠ€ν„΄μŠ€κ°€ static이기 λ•Œλ¬Έμ— 클래슀 λ‘œλ”©μ‹œμ μ— ν•œλ²ˆ 호좜될 것이며 final을 μ‚¬μš©ν•˜μ—¬ 값을 λ³€κ²½ν•˜μ§€ λͺ»ν•˜λ„둝 ν•˜μ˜€μŠ΅λ‹ˆλ‹€.

    이 방법이 κ°€μž₯ 많이 μ‚¬μš©ν•˜κ³  일반적인 Singleton 클래슀 방법이라고 ν•©λ‹ˆλ‹€.

    λ°˜μ‘ν˜•
Designed by Tistory.