hackerrank.com

Hackerrank.com Practice>Java>Advanced>Java Singleton Pattern

건이두 2019. 12. 2. 13:36
728x90

Singleton Pattern을 이해하고 있는지에 대해서 묻는 문제 입니다.

import java.io.*;
import java.util.*;
import java.lang.reflect.*;

class Singleton{
    private Singleton() {}
    private volatile static Singleton instance;
    public String str;

    static Singleton getSingleInstance() {
        if(null == instance) {
            synchronized(Singleton.class) {
                if(null == instance) {
                    instance = new Singleton();
                }
            }
        }

        return instance;
    }
}

이렇게 구현하는 것이 가장 일반적입니다.
2가지 동기화 문제를 고려해야 합니다.

  • volatile을 사용해서, instance 필드를 항상 메모리로 부터 읽어서, 첫번째 동기화 문제를 해결합니다.
  • static 메서드 안에서, Singleton class의 인스턴스를 생성할 때, 동기화 문제를 방지 하기 위해서, Singleton.class로 lock을 걸어 줍니다.
    • 만약에, getSingleInstance() 메서드가 static이 아니라면, (즉, 싱글턴 패턴이 아닌 일반 메서드라면) synchronized에 this를 사용할 수 도 있습니다.

holder 클래스를 사용해서 아래와 같이 코딩하는 것도 가능합니다. 하지만, 클래스가 로딩될 때, 인스턴스가 만들어저서, 사용하지 않는 대로, 인스턴스가 계속 만들어져 있는, 단점이 있습니다.

class Singleton{
    public String str;
    private Singleton() {}

     private class MyHolder {
        static Singleton instance = new Singleton();
    }

    static Singleton getSingleInstance() {
         return MyHolder.instance;
    }
}

아래와 같이 class level lock을 사용하지 않으면, 멀티 쓰레드 환경에서 호출 될 경우, 여러개의 인스턴스가 만들어질 수 도 있습니다. statick 메서드 이기 때문에, object level lock이 아닌 class level lock을 사용합니다.

class Singleton{
    private Singleton() {}
    private volatile static Singleton instance;
    public String str;

    static Singleton getSingleInstance() {
        if(null == instance) {
            instance = new Singleton();
         }

        return instance;
    }
}

Object level lock vs Class level lock in Java 에 대한 보다 깊은 내용은 아래 글을 참고하세요.
https://howtodoinjava.com/java/multi-threading/object-vs-class-level-locking/

728x90