정상에서 IT를 외치다

싱글톤이란? (feat. JAVA, Kotlin) 본문

카테고리 없음

싱글톤이란? (feat. JAVA, Kotlin)

Black-Jin 2021. 10. 6. 17:13
반응형

싱글톤은 소프트웨어 디자인 패턴 중의 하나로 오직 하나의 인스턴스만을 가진다. 

Singleton Pattern - Wiki

 

여기서 인스턴스는 OOP의 관점에서 객체가 메모리에 할당되어 실제 사용될 때를 가리킨다. 위키피디아에 따르면 싱글톤은 다음 5가지 방식으로 문제를 해결한다.

 

1. 클래스에 인스턴스가 하나만 있는지 확인
2. 클래스의 유일한 인스턴스에 쉽게 접근
3. 인스턴스화 제어
4. 인스턴스 수 제한
5. 전역 변수 접근

 

이렇게 함으로써 생성자를 숨길 수 있고 static 함수를 사용해 클래스에서 오직 1개의 인스턴스만을 반환할 수 있다. 근데 여기서 문제가 발생할 수 있다. 바로 멀티쓰레드에서 말이다.

 

멀티쓰레드에서의 문제

멀티쓰레드 환경에서 동시에 클래스에 접근하게 되면 문제가 발생할 수 있다. 싱글톤이지만 객체를 여러개 생성될 수 있다. 이를 위해 Lazy Loaded SingleTon (늦은 초기화) 와 Double-checked locking (DCL) 방식으로 이를 방지할 수 있다.

 

Lazy Loaded SingleTon - Wiki

public class Something {
    private Something() {}

    private static class LazyHolder {
        static final Something INSTANCE = new Something();
    }

    public static Something getInstance() {
        return LazyHolder.INSTANCE;
    }
}

위는 위키에 있는 예제이다. 여기서 중요한 것은 static class를 맴버 변수로 선언했다는 거다. 그렇게 되면 어떤 일이 일어날까? 위키의 내용 일부를 읽어보자.

The static class LazyHolder is only executed when the static method getInstance is invoked on the class Something, and the first time this happens the JVM will load and initialize the LazyHolder class.


static class 맴버 변수는 getInstance 될때 오직 1개만 JVM에서 생성해 준다는 것이다. JVM 스펙이므로 우리는 1개의 인스턴스만이 생성되고 사용되어 진다고 믿고 쓸수 있다. 


참고로 아래는 필자가 생각하는 위와 근접한 코틀린 코드 이다.
참고 - stackoverflow

class Something private constructor(){

    companion object {

        val instance: Something by lazy(LazyThreadSafetyMode.PUBLICATION) { Something() }
    }
}

 

Double-checked locking - Wiki

class Something private constructor(){

    companion object {
        private var instance: Something? = null

        fun getInstance() =
                instance ?: synchronized(this) {
                    instance ?: Something().also { instance = it }
                }
    }
}

인스턴스를 가져올 때 null 인지 확인힙니다. 또한 synchronized 블록에서도 한번 더 null 체크 후 값을 반환합니다. 이렇게 함으로써 멀티쓰레드 환경에서도 1개의 instance만 생성하여 사용할 수 있도록 합니다.

 

@Volatile

@Volatile private var instance: Something? = null

voltile 키워드는 Java 변수를 Mina Memory에 저장하겠다는 것을 명시하는 것입니다. 매번 변수의 값을 Read/Write 할 때마다 CPU cache에 저장된 값이 아닌 Main Memory에서 가져와서 사용합니다.

반응형
Comments