싱글톤 패턴 Singleton Pattern
1. 개념
싱글톤 패턴 (Singleton Pattern) 이란 인스턴스를 1개만 생성하는 디자인 패턴이다.
보통은 객체가 사용되는 시점마다 new 를 이용하여 인스턴스를 매번 생성하여 사용하지만,싱글톤 패턴은 오직 하나의 인스턴스를 메모리에 등록하여 동시에 여러 스레드가 공유하여 사용하는 방식을 채택한다. (이 때문에 반드시 Thread-safe가 보장되어야 함)
2. 싱글톤 패턴 - 가장 심플한 버전
# Eager Initialization # 이른 초기화 # Thread-safe
이른 초기화 싱글톤 패턴의 핵심은 다음과 같다.
(1) create an object of SingleObject
- 클래스 멤버로 인스턴스 생성 (이후 여러 스레드에서 공유되어 사용될 인스턴스. static으로 정의되어야 함)
- static 은 정적 바인딩되기 때문에 클래스 로더가 초기화되는 시점 (컴파일단계) 에서 인스턴스가 메모리에 등록됨.
-> 따라서 Thread-safe 보장!
(2) make the PRIVATE contructor
- 반드시 private 생성자를 정의할 것 (외부에서 아무나 생성자를 호출해서 인스턴스를 생성해서는 안 됨)
(3) get the ONLY object available
- 인스턴스를 반환하는 메소드 생성 (static으로 정의되어야 함)
🔻SingleObject.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
public class SingleObject {
// (1) create an object of SingleObject
private static SingleObject instance = new SingleObject();
// (2) make the constructor private so that this class cannot be
//instantiated
private SingleObject(){}
// (3) Get the only object available
public static SingleObject getInstance(){
return instance;
}
public void showMessage(){
System.out.println("Hello World!");
}
}
|
cs |
🔻 SingletonParrernDemo.java
1
2
3
4
5
6
7
8
9
10
|
public class SingletonPatternDemo {
public static void main(String[] args) {
//Get the only object available
SingleObject object = SingleObject.getInstance();
//show the message
object.showMessage();
}
}
|
cs |
Demo 클래스에서는 SingleObject의 getInstance 메소드를 통해 단일 인스턴스를 받아올 수 있다.
❗이때, SingleObject object = new SingleObject() 로 인스턴스를 생성하면 The constructor SingleObject() is not visible 라는 컴파일에러가 발생한다. 애초에 외부에서 임의로 인스턴스생성하는것을 막기 위해 생성자를 private으로 정의했기 때문이다.
3. 싱글톤 패턴 - 개선된 버전
# Lazy Initialization # 동기화 블럭 # Thread-safe
앞서 제시된 심플한 버전의 싱글톤 패턴은 몇 가지 문제가 존재한다.
1. Exception handling 불가능
2. 인스턴스가 필요하지 않을 때에도 무조건 생성 -> resource wastage
이 문제점을 개선한 것이 다음 Lazy Initilization 버전의 싱글톤 패턴이다.
(1) synchronized method
- Exception handling을 하기 위해 static method 내부에서 객체가 생성되도록 한다.
- 이때, Thread-safe 하지 않기 때문에 synchronized 로 쓰레드의 동시접근을 막는다. (Method 단의 동시성 제어)
(2) instance가 null일 경우에만 생성하여 자원낭비를 막는다.
(3) volatile 키워드를 사용.
- 원래의 MultiThread 어플리케이션에서는 Task를 수행하는 동안 성능 향상을 위해 Main Memory에서 읽은 변수 값을 CPU Cache에 저장하게 된다. 만약에 Multi Thread환경에서 Thread가 변수 값을 읽어올 때 각각의 CPU Cache에 저장된 값이 다르기 때문에 변수 값 불일치 문제가 발생하게 될 수 있다.
- 따라서 volatile 키워드를 사용하여 변수의 값을 Read할 때마다 CPU cache에 저장된 값이 아닌 Main Memory에서 읽도록 명시한다.
🔻 Lazysingleton.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
public class LazySingleton
{
private volatile static LazySingleton instance;
private LazySingleton(){}
public static LazySingleton getInstance() {
if (instance == null)
{
//synchronized block to remove overhead
synchronized (LazySingleton.class)
{
if(instance==null)
{
instance = new LazySingleton();
}
}
}
return instance;
}
}
|
cs |
❗ 이 경우 기능적으로는 잘 동작하지만 성능저하가 발생할 수 있다.
instance를 생성할때만 동시접근을 막으면 되는데 method전체를 synchronized 처리를 해버려서 인스턴스호출 자체도 막히게 된다.
💡 그래서 대신 synchronized block 을 사용한다!
- method 전체가 아니라 instance 생성하는 부분만 synchronized block처리를 하면 return되는 부분은 자유로워진다.
🔻 Lazysingleton.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
public class LazySingleton
{
private volatile static LazySingleton instance;
private LazySingleton(){}
public static LazySingleton getInstance() {
if (instance == null)
{
//synchronized block to remove overhead
synchronized (LazySingleton.class)
{
if(instance==null)
{
instance = new LazySingleton();
}
}
}
return instance;
}
}
|
cs |
3. 싱글톤 패턴 - 가장 많이 사용되는 버전
# Lazy Holder # 게으른 홀더 # Thread-safe
참고자료
https://www.tutorialspoint.com/design_pattern/singleton_pattern.htm
https://www.geeksforgeeks.org/java-singleton-design-pattern-practices-examples/
https://nesoy.github.io/articles/2018-06/Java-volatile
'ComputerScience > Network & Web' 카테고리의 다른 글
DNS에 대하여(2) - DNS 동작원리 (0) | 2022.03.30 |
---|---|
DNS에 대하여(1) - displaydns, flushdns 명령 (0) | 2022.03.30 |
ARP 캐시 테이블에 대하여 (0) | 2022.03.29 |
DHCP, DNS, Physical Address - ipconfig/all 명령 (0) | 2022.03.29 |
IP address, subnet mask, gateway - ipconfig 명령 (0) | 2022.03.17 |