Post

싱글톤 패턴

싱글톤 패턴

해당 클래스의 인스턴스가 하나만 만들어지고, 어디서든지 그 인스턴스에 접근할 수 있도록 하기 위한 패턴

고전적인 싱글톤 패턴 (문제 있음)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Singleton {

  private static Singleton uniqueInstance;

  private Singleton() {
  }

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

멀티쓰레드 환경에서는

1
2
3
if(uniqueInstance==null){
  uniqueInstance=new Singleton();
  }

이 부분에서 2개 이상의 인스턴스가 생성될 수 있다.

해결방법

1. synchronized 사용

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Singleton {

  private static Singleton uniqueInstance;

  private Singleton() {
  }

  public static synchronized Singleton getInstance() {
    if (uniqueInstance == null) {
      uniqueInstance = new Singleton();
    }
    return uniqueInstance;
  }
}
  • 단점 : 속도 저하

    → 메소드가 synchronized 되면 약 100배 정도 성능 저하가 일어난다고 한다.

2. 인스턴스를 처음부터 만들어 버림

1
2
3
4
5
6
7
8
9
10
11
public class Singleton {

  private static Singleton uniqueInstance = new Singleton();

  private Singleton() {
  }

  public static synchronized Singleton getInstance() {
    return uniqueInstance;
  }
}
  • 클래스가 로딩될 때 JVM에서 Singleton의 유일한 인스턴스를 생성해준다.

3. DCL(Double-Checking Locking) 사용

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Singleton {

  private volatile static Singleton uniqueInstance;

  private Singleton() {
  }

  public static Singleton getInstance() {
    if (uniqueInstance == null) {
      synchronized (Singleton.class) {
        if (uniqueInstance == null) {
          uniqueInstance = new Singleton();
        }
      }
    }
    return uniqueInstance;
  }
}
  • volatile 키워드를 사용하면 자바의 일종의 최적화인 리오더링(보통 컴파일 과정에서 일어나며, 프로그래머가 만들어낸 코드는 컴파일 될 때 좀더 빠르게 실행될 수 있도록 조작이 가해져 최적하됨)을 회피하여 읽기와 쓰기순서를 보장한다.
  • 멀티스레딩을 쓰더라도 uniqueInstance변수가 Singleton 인스턴스로 초기화 되는 과정이 올바르게 진행되도록 할 수 있다.
  • DCL은 자바1.5이상의 버전에서만 사용가능하다.
  • 자바 1.4 및 그 전에 나온 버전의 JVM 중에는 volatile 키워드를 사용하더라도 동기화가 잘 안되는 것이 많다. 일종의 버그.

요약

  • 우리가 알고있던 싱글톤 패턴은 사실 싱글톤 패턴이 아님!
  • 위의 3가지 방법을 사용하자
  • 개인적으론 생성자(2번)가 가장 간단한 것 같음
This post is licensed under CC BY 4.0 by the author.