dev/🧩 디자인패턴
싱글턴 패턴 - 동시성 문제 해결
wugawuga
2022. 10. 25. 13:38
아래 코드는 느린 초기화로 불리는 Lazy Initialization, 전 글에서 보았던 전형적인 싱글턴 구현법이다.
여러 스레드에서 getInstance() 를 호출하고 동시에 if 문을 타게 되다면 null이라 판단하여 인스턴스가 두 번 생성된다.
public class Singleton {
private static Singleton unique;
private Singleton() {
}
public static Singleton getInstance() {
if (unique == null) {
unique = new Singleton();
}
return unique;
}
}
멀티 스레드 환경을 만들어 간단히 동시성 문제를 발생시켜 보았다.
동시성 문제 해결법은??
1. synchronized 키워드 추가
public class Singleton {
private static Singleton unique;
private Singleton() {
}
public static synchronized Singleton getInstance() {
if (unique == null) {
unique = new Singleton();
}
return unique;
}
}
synchronized 는?
- 스레드간 동기화를 시켜 thread-safe 하게 해줌
- 여러개의 스레드가 하나의 자원을 사용하고자 할 때
- 남발하면 성능저하
2. DCL (Double Checked Locking)
두번 체크! synchronized 위치를 바꾸면서 동기화 오버헤드를 낮춤
public class Singleton {
private static Singleton unique;
private Singleton() {
}
public static Singleton getInstance() {
if (unique == null) {
synchronized (Singleton.class) {
if (unique == null) {
unique = new Singleton();
}
}
}
return unique;
}
}
인텔리제이에선 DCL 을 바로 파악하고 holder 방법으로 권유한다.
3. Holder
클래스 로딩 단계에서 전역 인스턴스를 생성하지 않는 장점
getInstance() 호출 시 생성된다. 많은 블로그를 보았는데 다 이 방식을 추천한다.
public class Singleton {
private Singleton() {
}
public static Singleton getInstance() {
return Holder.instance;
}
private static class Holder {
public static final Singleton instance = new Singleton();
}
}