Design Patterns

[Design Patterns] 싱글턴 패턴(Singleton)

BlueSwamp 2014. 2. 11. 11:28
반응형

싱글턴 패턴은 해당 클래스의 인스턴스가 하나만 만들어지고, 어디서든지 그 인스턴스에 접근할 수 있도록 하기 위한 패턴이다.


사용하는 이유

하나만 있으면 되는 스레드 풀, 캐시, 대화상자, 사용자 설정, 레지스트리 설정을 처리하는 객체, 로그 기록용 객체, 프린터나 그래픽 카드 같은 디바이스를 위한 디바이스 드라이버 등 객체를 쓸 때 인스턴스를 두 개 이상 만들게 되면 프로그램이 이상하게 돌아가거나, 자원을 불필요하게 잡아먹어 결과의 일관성이 없어지는 것같은 문제가 발생할 수 있다.


싱글턴 vs 전역 변수

싱글턴과 전역 변수는 어디서든지 엑세스할 수 있지만, 전역 변수는 플렛폼에 따라 다르지만 애플리케이션이 시작될 때 생성 되어 자원을 차지한다. 만약 끝날 때까지 사용하지 않는다면 자원을 차지하게 된다. 하지만 싱글턴 패턴을 사용하면 필요할 때만 객체를 만들게 된다.


고전적인 싱글턴 패턴

이 코드를 사용 할 경우 문제가 발생하기 때문에 다른 방법을 사용한다.

public class Singleton {

      // 유일한 인스턴스를 저장하기 위한 정적 변수

private static Singleton uniqueInstance;

// 생성자가 private로 선언을 했기 때문에 Singleton에서만 클래스의 

// 인스턴스를 만들 수 있다.

private Singleton() {}

// getInstance()에서 null일 경우에만 생성을 하고 있을 경우는 그대로 

// 반환하여 유일한 인스턴스가 만들어 진다.

publilc static Singleton getInstance() {

if(uniqueInstance == null) {

uniqueInstance = new Singleton();

}

return uniqueInstance;

}

}


고전적인 싱글턴 패턴의 문제점

고전적인 싱글턴 패턴에 문제는 여러개의 스레드를 사용하게 되면서 문제가 발생하였다. 1번 스레드와 2번 스레드에서 동시에 사용하게될 경우 동시에 진입이 되어 진행된다. 그 결과 2개의 인스턴스가 만들어 지게 된다.


멀티스레딩 문제 해결 방법

위 문제를 해결하기 위해서는 3가지 방법이 있다. 아래 내용은 JAVA에서 사용되는 방법이므로 다른 언어에서는 다른 방법으로 변환하여 사용해야 한다.

1. getInstance()의 속도가 중요하지 않을경우 synchronized를 사용

동기화를 시킬경우 끝나기를 기다려야 하기 때문에 성능이 저하된다.


2. 인스턴스를 필요할 때 생성하지 말고, 처음부터 만들어 버린다.


3. DCL(Double-Checking Locking)을 사용하여 getInstance()에서 동기화되는 부분을 줄인다.

DCL을 사용하면, 인스턴스가 생성되어 있는지 확인한 다음, 생성되어 있을 않았을 때만 동기화를 할 수 있다. 이렇게 하면 처음에만 동기화를 하고 나중에는 동기화를 하지 않아도 된다.


참고 : HeadFirst Design Patterns

반응형