티스토리 뷰

LANGUAGE/DESIGN PATTERN

[DESIGN PATTERN] SINGLETON PATTERN

진심스테이크 2019. 7. 15. 17:25

 

Singleton Pattern : 클래스의 인스턴스(객체)가 오직 1개만 생성되도록 하는 것

- 필요할 때마다 똑같은 인스턴스를 만드는게 아니라, 이미 생성해둔 기존 인스턴스를 사용

- 전역 인스턴스로 만들기 떄문에 다른 클래스의 인스턴스들이 데이터를 공유하기 쉬움

- 메모리 낭비를 막음

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Singleton {
 
    // static : 단 하나의 인스턴스만 담기 위함
    private static Singleton instance;
 
    private Singleton() {}
 
    // private으로 선언된 instance를 다른 클래스에서 사용하기 위함
    public static Singleton getInstance() {
 
        //메모리 낭비를 막기위해 객체를 사용할 때 할당해주겠다
        if (instance == null) { // 객체가 없으면 생성
            instance = new Singleton();
        }
        
        // 있으면 리턴
        return instance;
    }
}
cs

 

 

문제점 : 동기화 문제

- 싱글 스레드를 사용할 경우에는 상관없지만, 멀티 스레드를 사용할 경우 문제가 생김

 

- 해결방안 1 : synchronized 사용

#synchronized : 여러개의 쓰레드가 하나의 자원에 접근하려 할 때, 주어진 순간에는 오직 하나의 쓰레드만 접근 가능하게 함

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//동기화 문제 해결방법1
class Singleton01 {
 
    private static Singleton01 instance;
 
    private Singleton01() {}
 
    public static synchronized Singleton01 getInstance() {
 
        if (instance == null) {
            instance = new Singleton01();
        }
 
        return instance;
    }
}
cs

 

- 위와 같이 할 경우, block / nonblock을 처리하면서 성능이 저하됨

- 해결방안 2 : Thread safe Lazy initialization + Double-checked locking

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//동기화 문제 해결방법2
class Singleton02 {
 
    private static Singleton02 instance;
 
    private Singleton02() {}
 
    public static Singleton02 getInstance() {
 
        // 객체가 없는 경우에만
        synchronized (Singleton02.class) {
            if (instance == null) {
                instance = new Singleton02();
            }
        }
 
        return instance;
    }
}
cs

 

- 더 좋은 방법 1 : Initialization on demand holder idiom (Holder에 의한 초기화 방식)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//동기화 문제 해결방법3
class Singleton03 {
 
//    private static Singleton03 instance;
 
//  일을 할 때만 메모리 할당 
    private static class LazyHolder {
        static final Singleton03 instance = new Singleton03();
    }
    
    private Singleton03() {}
 
    public static Singleton03 getInstance() {
        
        return LazyHolder.instance;
    }
}
cs

 

- 더 좋은 방법 2 : enum 이용

#enum : 상수들만 뫃아놓은 클래스

1
2
3
4
5
6
7
8
//동기화 문제 해결방법4
public enum Singleton04 {
    INSTANCE; //static final
 
    public static Singleton04 getInstance() {
        return INSTANCE;
    }
}
cs

 

'LANGUAGE > DESIGN PATTERN' 카테고리의 다른 글

[DESIGN PATTERN] DECORATOR PATTERN  (0) 2019.07.15
[DESIGN PATTERN] STRATEGY PATTERN - 전략 패턴  (0) 2019.07.15
[DESIGN PATTERN] BASIC THINGS  (0) 2019.07.15
댓글