2023. 10. 21. 16:28ㆍ디자인패턴
문제 배경
오직 하나뿐인 객체를 만들고 싶다.
어떻게 만들 수 있을까?
1.
public MyClass {
private MyClass() {}
}
이렇게 만들어버리면 클래스 생성자체를 못한다.
2.
public MyClass {
private MyClass() {}
public static MyClass getInstance() {
return new MyClass();
}
}
이렇게 만들면 외부에선 생성하지 못하지만
내부에선 여러개의 클래스 생성가능
Singleton Pattern
public class Singleton {
private static Singleton uniqueInstance;
// other useful instance variables here
private Singleton() {}
public static Singleton getInstance() {
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
// other useful methods here
}
이렇게 만들면 오직 하나뿐인 객체를 만들 수 있다.
Singleton m=Singleton.getInstance();
Singleton n=Singleton.getInstance();
/*uniqueInstance 변수가 처음에 만들어진 객체를 가리키고 있으므로 null이 아니게 된다.
그러므로 처음 만들어진 객체를 가리키게 된다.
결국 m,n 둘다 같은 객체를 가리키게 됨.
*/
그리고 생성자가 private이고
getInstance메소드는 static 메소드이기 때문에
new singleton(); 으로 생성할 수 없고
singleton.getInstance();로만 생성 가능
멀티스레드 환경에서도 하나의 객체만 만들고 싶을 때
public class Singleton {
private static Singleton uniqueInstance;
// other useful instance variables here
private Singleton() {}
public static synchronized Singleton getInstance() {
//synchronized 키워드를 사용하여 getInstance함수가 종료될때까지 다른 스레드는 락에 걸려있게 됨.
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
// other useful methods here
}
문제점: 처음에 객체를 만들고 난 뒤로는 synchronized 키워드가 필요없다
해결책: double-checked locking을 사용
public class Singleton {
private volatile static Singleton uniqueInstance; //volatile 키워드를 사용
private Singleton() {}
public static Singleton getInstance() {
if (uniqueInstance == null) {
synchronized (Singleton.class) {//이 블록 안의 코드만 synchronized 적용,class 동기화
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
}
}
return uniqueInstance;
}
}
* 객체가 null 일 경우에만 synchronized가 실행되도록 하여 객체가 생성된 후에는 synchronized가 실행되지 않는다.
즉, 무분별한 synchronized 호출의 비용을 절약할 수 있다.
* volatile 키워드: thread safety 보장 위한 키워드
키워드로 지정을 하지 않으면 각 스레드는 변수의 복사본을 유지해
변수를 변경해도 실제 값은 변경이 안되고 복사본만 변경된다.
volatile 지정된 변수를 변경 시
-> 스레드가 메모리에 저장된 실제 값을 읽어옴(실제로 값 변경)
* 동작 과정
1. 첫번째 스레드에서
null인가? -> 그렇다. class 생성자 호출
2. 첫번째 스레드 sleep
3. 두번째 스레드에서
null인가? -> 그렇다. class 생성자 호출
4. 두번째 스레드 sleep
5. 첫번째 스레드
null인가 ? -> 그렇다. class 생성
6. 두번째 스레드
null인가 ? -> 첫번째 스레드에서 생성되었으므로 생성x
'디자인패턴' 카테고리의 다른 글
| The Adapter and Facade Patterns (0) | 2023.10.21 |
|---|---|
| The Command Pattern (1) | 2023.10.21 |
| Decorator Pattern (2) | 2023.10.21 |
| The observer pattern (0) | 2023.10.19 |
| Strategy Pattern (0) | 2023.10.18 |