어흥

[CS] 싱글톤 패턴 본문

CS

[CS] 싱글톤 패턴

라이언납시오 2022. 2. 24. 20:30
728x90
반응형

1. 싱글톤 패턴이란?

Java: Class는 ClassLoader당 1번만 인스턴스화가 되어야 한다

Spring: BeanScope를 정의하는 한가지 방법

 

2. 구현 방법

1) Eager Initialization

[Eager Initialization] - 이른 초기화
#1. 외부에서 접근하지 못하도록 private static한 인스턴스 생성
#2. 외부에서 생성자 호출하지 못하도록 private으로 설정
#3. 인스턴스를 반환해주는 메소드는 어디서든 접근 가능하도록 public static으로 설정

public class Singleton {
    private static Singleton instance = new Singleton();
    
    private Singleton() {
        // 생성자는 외부에서 호출못하게 private 으로 지정해야 한다.
    }

    public static Singleton getInstance() {
        return instance;
    }
}

특징: 클래스로더에 의해 클래스가 로딩될 때 싱글톤 객체를 미리 생성
장점: Thread-safe
단점: 싱글톤 객체를 미리 생성 → 메모리를 잡아먹는다

언제 사용?
항상 싱글톤 객체 필요 or 객체 생성비용↓

 

 

2) Static Block Initialization

[StaticBlockInitialization]
#1. Eager Initialization과 비슷하지만, 인스턴스를 생성하는 위치가 static initializer block내에 존재한다

public class StaticBlockInitialization {
	private static StaticBlockInitialization singletonInstance;

	private StaticBlockInitialization() {}

	static {
		try {
			singletonInstance = new StaticBlockInitialization();
		} catch (Exception e) {
			throw new RuntimeException("싱글톤 인스턴스 생성과정에서 예외가 발생했습니다");
		}

	}

	public static StaticBlockInitialization getInstance() {
		return singletonInstance;
	}

};

 

3) Lazy Initialization

[Lazy Initailization]
#1. 클래스가 로딩되고, 최초 호출이 생긴다면 인스턴스를 생성한다

public class Main {
	public static void main(String args[]) {
		Singleton singleton = Singleton.getInstance();
		System.out.println("Value 1 : " + singleton.getValue());		//10
		singleton.setValue(20);
		Singleton singleton2 = Singleton.getInstance();
		System.out.println("Value 2: " + singleton2.getValue());		//20
	}
}

class Singleton {
	private Singleton() {
	}

	private static Singleton singleton;
	private int value = 10;

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

	public int getValue() {
		return value;
	}

	public void setValue(int value) {
		this.value = value;
	}
}

특징: 인스턴스가 최초로 사용되는 시점에 인스턴스를 생성한다
장점: 사용시점까지 객체 생성을 미뤄 메모리 낭비 X
단점: MultiThread에서 동시에 인스턴스 생성 요청시 처리하지 못한다

 

4) Thread Safe Lazy Initialization

[ThreadSafeLazyInitialization]
#1. Lazy Initialization의 단점인 Thread-safe하지 않은 점을 보완하기 위해 Synchronized 키워드를 통해 동시성을 해결

public class ThreadSafeLazyInitialization{
	private static ThreadSafeLazyInitialization instance;
	
	private ThreadSafeLazyInitialization() {}
	
	public static synchronized ThreadSafeLazyInitialization getInstance() {
		if(instance == null) {
			instance = new ThreadSafeLazyInitialization();
		}
		return instance;
	}
	
}

장점: 늦은 초기화와 Thread Safe의 장점을 가진다
단점: Synchronized 키워드를 사용할 경우, 자바 내부적으로 해당 영역이나 메소드를 lock/unlock
처리하기 때문에 많은 비용이 발생 → 성능저하 유발

 

5) ThreadSafeLazyInitialization + DCL

[ThreadSafeLazyInitialization + Double-Checked Locking]
#1 ThreadSafeLazyInitialization의 성능을 개선하기 위해 인스턴스가 null일 때, synchronized 블록을 탄다
public class ThreadSafeLazyInitialization {

	private static ThreadSafeLazyInitialization instance;

	private ThreadSafeLazyInitialization() {}

	public static ThreadSafeLazyInitialization getInstance() {
		// Double-checked locking
		if (instance == null) {
			synchronized (ThreadSafeLazyInitialization.class) {
				if (instance == null)
					instance = new ThreadSafeLazyInitialization();
			}

		}
		return instance;
	}
}

장점: ThreadSafeLazyInitialization의 단점인 성능저하를 보완할 수 있다
단점: 캐시와 관련된 문제가 존재 → Volatile을 사용해야 한다 → 성능 문제 발생

※Volatile
1. Volatile 변수는 CPU의 Cache를 거치지 않고 메인 메모리에 직접 R/W 수행
2. Volatile 변수에 대한 접근(R/W)은 Synchronized를 사용하는것과 동일하게 동작
3. Primitive과 Object(Null 허용) 타입 모두 사용 가능

 

3. 싱글톤의 장단점

장점)

1. 최초 한번의 new 연산자를 통해 고정된 메모리 영역 사용 → 메모리 낭비 방지

2. 이미 생성된 인스턴스 활용 → 속도 측면에서 이득

3. 다른 클래스 간에 데이터 공유가 쉽다

 

단점)

1. 동시성 문제를 해결해야 한다(synchronized 키워드)

2. 테스트하기 어렵다(자원 공유로 인해 매번 초기화해야 한다)

3. 클라이언트가 구체 클래스에 의존하게 된다 → DIP 위반 + OCP 위반 가능성 높다

4. 자식 클래스 생성 불가

5. 내부 상태 변경 어려움

 

4. Spring의 Singleton

- BeanScope를 정의하는 한가지 방법(Default값)

- Thread-safe하다

- 한번 생성되면 어디에서든 공유 가능하기 때문에 어떠한 상태도 가지면 안된다

 

 

[참고 자료]

https://javabeat.net/spring-singleton-java-singleton/

https://gem1n1.tistory.com/96

https://limkydev.tistory.com/67

https://alphahackerhan.tistory.com/36

728x90
반응형

'CS' 카테고리의 다른 글

[CS] 동시성 제어  (1) 2022.03.18
[CS] 필기 및 면접 대비 블로그  (0) 2021.03.24
Comments