싱글톤 패턴

김아무개·2023년 5월 8일

Java

목록 보기
9/23

책을 보다가 싱글톤 패턴에 대한 코드를 봤는데,
내가 사용하는 코드와 다른 방식으로 설명을 해서
챗봇에게 책에서 본 코드와 내가 사용하는 코드를 비교해서 설명해달라고 부탁했다.

결론부터 얘기해보자면
두개는 다른 패턴의 싱글톤 구현 코드였고,
내가 사용하던 코드에는 심지어 문제가 있었다. 🙊

스레드 안전성이 없다고 한다,

관련해서 두 가지 문제점을 지적받았는데,

첫 번째로

synchronized 블록을 사용하지 않았기 때문에
여러 스레드가 동시에 getInstance()에 접근하게 된다면 Hello 인스턴스가 여러번 생성될 수 있는 문제가 있었고,

두 번째로는

멀티스레드 환경에서
Hello 인스턴스를 생성한 후 다른 스레드가 이것을 볼 수 없는 경우가 발생할 수 있다고 한다.
인스턴스 생성 과정에서 컴파일러 최적화와 CPU 캐시 메모리의 동기화 문제 때문이었다.
이 문제를 해결하려면 volatile 키워드를 사용해서 INSTANCE 변수를 생성하면 된다.

volatile 키워드는 변수가 항상 메인 메모리에서 읽고 쓰여야 함을 나타내고,
이를 통해 모든 스레드가 항상 최신 값을 볼 수 있도록 한다고 한다.


이제 내가 사용하던 문제가 있는 코드를 소개하자면 다음과 같다.

public class Hello {
	private static Hello INSTANCE;
    private Hello() {}
    public static Hello getInstance() {
    	if (INSTANCE == null) INSTANCE = new Hello();
        return INSTANCE;
    }
}

이거였고,
코칭 받아 수정된 코드는 다음과 같다.

class Hello {
    private static volatile Hello INSTANCE;
    private Hello() {}
    public static Hello getInstance() {
        if (INSTANCE == null) {
            synchronized (Hello.class) {
                if (INSTANCE == null) INSTANCE = new Hello();
            }
        }
        return INSTANCE;
    }
}

그리고 책에서 본 코드는

class Hello {
	public static class SingleInstanceHolder {
    	private static final Hello INSTANCE = new Hello();
    }
    public static Hello getInstance() {
    	return SingleInstanceHolder.INSTANCE;
    }
}

이거였다.

내가 사용하는 코드는
Double-checked Locking 패턴을 사용한 방식이고 (약간 잘못 사용하고 있었지만 🥲)

책에서 본 코드는
Initialization on Demand Holder 패턴을 사용한 방식이라고 한다.
이 패턴을 사용하면 간단하게 스레드 안전성을 보장받을 수 있다.


챗봇은 Initialization on Demand Holder 패턴의 단점으로
코드 가독성의 어려움을 꼽았는데,

내가 봤을 땐 Double-checked Locking 패턴이 더 어려운 것 같다..ㅋㅋㅋ ㅠㅠ


싱글톤 패턴을 얼마나 사용 하게 될 지는 모르겠지만..
그래도 잘못 알고있었던 부분에 대해 바로 잡을 수 있어서 좋은 기회였다고 생각한다. 🤓

profile
Hello velog! 

0개의 댓글