Singleton Pattern
class의 단 하나의 instance를 만들고자하는 패턴
구현
new 연산자를 사용하지 않고(private constructor) 함수(static method. 외부에서 Instance 없이 접근할 수 있도록)를 통해 인스턴스 생성한다.
※ constructor를 안 만들면 기본적으로 public constructor가 생성된다.
getInstance함수를 통해서 내부의 uniqueInstance를 리턴해준다.
이 때, 밖에서 변경하지 못하도록 uniqueInstance는 private로 변경하고, static getInstance()에서 사용해야하기 때문에 static variable로 만들어준다.
그러나 이 코드는 아래와 같은 문제가 있다.
예시)
Multi-thread에서 Singleton Pattern
위 코드로 진행하면 Multi-thread에서 오류(Instance가 최대 Thread 수만큼 생성)가 날 수 있다.
해결 방안 1
getInstance method를 호출할 때 동시에 호출할 수 없도록 synchronized를 추가한다.
한 thread가 해당 method를 모두 완료하고 나가고 나서야 호출할 수 있다.
하지만 thread가 많다고하면
과도한 locking overhead가 존재한다.
해결 방안 2
uniqueInstance를 처음부터 생성해준다.
아래와 같이 하면 multi-thread여도 문제가 없고, lock overhead도 존재하지 않는다.
하지만 이 경우 누가 요청하지 않아도 미리 생성하는 것인데. (global variable과 동일)
메모리 효율성에서는 좋지 않다.
해결 방안 3
lock을 함수 진입에 하면 과도한 overhead가 존재하니 write할 때만 lock을 설정한다. (read 할 때는 lock 필요 없음)
lock 후, uniqueInstance 존재를 double-check한다.
(두 thread가 getInstance()함수에서 if문에 위치하고 A thread가 생성하고 나가고 B thread가 if문에서 들어온 뒤에 null확인이 없으면 새로 인스턴스를 생성하게 된다)
논리적으로는 문제가 없지만
실제로 돌려보면 가아끔 특수한 문제가 생긴다.
A thread가 instance를 생성하는 도중에
B thread가 생성 중인 instance를 read하고 이것저것 부르고 접근하려고 할텐데
완전하게 생성되지 않았기 때문에 런타임에러가 날 수 있다.
해결 방안 4
위 모든 문제를 해결하는 최종 코드이다. (java 1.5이후부터 가능)
'💻 개발IT > Design Patterns' 카테고리의 다른 글
5. Structural 패턴 - Bridge Pattern (0) | 2022.03.10 |
---|---|
5. Structural 패턴 - Composite Pattern (0) | 2022.03.09 |
5. Structural 패턴 - Adapter Pattern (0) | 2022.03.06 |
5. Structural 패턴 - Decorator Pattern (0) | 2022.03.05 |
4. Creational 패턴 - Builder Pattern (0) | 2022.03.03 |
4. Creational 패턴 - Abstract Factory Method Pattern (0) | 2022.03.02 |
4. Creational 패턴 - Factory Method Pattern (0) | 2022.03.02 |
3. Behavior 패턴 - Mediator Pattern (0) | 2022.03.01 |