언어/Java

Java(자바) - 멀티쓰레드(Multi Thread) 상황에서의 싱글톤(Singleton)

[좋은사람] 2017. 9. 10. 16:22

Java(자바) - Multi Thread 환경 안에서 Singleton

 

 

(1). 개요

Java 에서 일반적으로 하나의 인스턴스를 사용하여 JVM 성능향상을 위해 싱글톤(Single) 패턴을 사용한다.

 싱글 쓰레드(Single Thread) 환경에서 사용 하는 기존 Singleton은 Multi Thread 환경에서 인스턴스 접근 시 문제가 있다.

③ 메소드에 synchronized 키워드 사용 할 경우 멀티쓰레드 환경에서 운영비용 및 오버헤드가 큰 것으로 증명되어 있다.

 유명 개발자들 사이에서 이 문제를 해결하기 위한 여러 방안이 제시되었고 아래와 같이 소개해 보려고 한다.

 

 

(2). Double Checked Locking

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//DclPattern.java
 
public class Singleton {
  private volatile static Singleton instance;
  private Singeton() {}
  
  public static Singleton getInstance() {
    if (instance == null)  {
        synchronized(Singleton.class) {
          if (instance == null) {
              instance == new Singleton();  
          }
        }
    }
    
    return instance;
  }
}
 
 
 
/*
    메소드에 synchronized 를 제거하였지만, 인스턴스 생성 후 
    사용 진입 과정에서 한 쓰레드에서 객체 생성이 되지 않으면
    오류가 발생할 수 있는 코드이며, 사용은 권장하지 않는다.
*/
 
 
cs

  보통은 싱글톤 객체를 가져오는 메소드명은 getInstance()작명하는 것이 표준이라고 볼 수 있다. 

 

(3). Enum -  직렬화 패턴


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//EnumPattern.java
 
public enum Singleton {
  INSTANCE;  
}
 
 
 
/*
    Enum 패턴은 단 한번의 인스턴스 생성을 보장하고 사용이 간편하다.
    자동 직렬화가 지원되는 이점이 있지만, 안드로이드 (Android) 등 개발 시에는    
    추가된 메소드가 safe 하지 않을 가능성이 있다.
    물론, 전역 접근도 가능하다.
*/
 
 
cs


(4). Lazy Initialization -  Lazy Loading 패턴

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
 
//LazyPattern.java
 
public class Singleton {
  private Singleton() {}
  public static Singleton getInstance() {
    return LazyHolder.INSTANCE;
  }
  
  private static class LazyHolder {
    private static final Singleton INSTANCE = new Singleton();  
  }
}
 
 
 
/*
    인스턴스 생성을 지연하는 기법이다. 클래스 변수(INSTANCE)의 반환을
    LazyHolder.INSTANCE 를 참조하는 순간 Class가 로딩됨으로써 초기화가   
    진행된다. synchronized 키워드 없이 동작하며, 당연히 thread-safe 하면서
    성능도 보장한다. 아직까지는 문제점이 보고되지 않았다.
*/
 
 
cs