본문 바로가기
Programming/Android

Android MultiThread 에서의 SingleTon 패턴

by ciwhiz 2020. 5. 12.

Effective Java에서는 SingleTon 패턴을 위해 Enum을 활용하는 것을 제안하기도 하지만,

Context 라는 개념이 있는 Android에서는 적합하지 않다.

Singleton의 초기화 과정에 context의 의존성이 끼어들 여지가 있기때문이다.

좋은 참고글  https://medium.com/@joongwon/multi-thread-%ED%99%98%EA%B2%BD%EC%97%90%EC%84%9C%EC%9D%98-%EC%98%AC%EB%B0%94%EB%A5%B8-singleton-578d9511fd42

 

Multi Thread 환경에서의 올바른 Singleton

일반적으로 하나의 인스턴스만 존재해야 할 경우 Singleton 패턴을 사용하게 된다. 물론 Single Thread에서 사용되는 경우에는 문제가 되지 않지만 Multi Thread 환경에서 Singleton 객체에 접근 시 초기화 ��

medium.com

결론적으로 Android Singleton 패턴을 사용하고자 한다면 LazyHolder 기법을 사용하자.

기본 코드 

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

객체를 사용하고자 할 때 초기화를 미루는(lazy) 것.

Singleton 클래스에는 LazyHolder 클래스의 변수가 없으므로, Sinlgeton 클래스 로딩 시에 

LazyHolder 클래스를 초기화하지 않음. LazyHolder 클래스는 Singleton 클래스의 getInstance()에서 
LazyHolder.INSTANCE 를 참조하는 순간 class가 로딩되며 초기화가 진행. 
Class를 로딩하고 초기화하는 시점을 code를 작성한 프로그래머가 아닌, system(framework)에 맡기는 것이므로

thread-safe 할 수 있다고 볼 수 있다. 그러므로 volatile, synchronized 키워드없이 thread-safe 하면서도 성능이 

보장된 기법. (synchronized 키워드를 사용하면 성능이 많이 떨어지는 것으로 알려져있다.)

 

다른 글(memoery leak을 피하는 방법)에도 나오지만, 

inner class(여기서는 LazyHolder class)를 static으로 생성하면,

outer class(여기서는 Singleton class)에 대해 의존성 reference를 갖지않는다.