'Singleton'에 해당되는 글 1건

  1. 2008/01/23 :: Java에서 Singleton 패턴 제대로 구현하기
2008/01/23 10:59

:: Java에서 Singleton 패턴 제대로 구현하기

Java 를 사용하여 Singleton 패턴을 구현할 경우 주의해야 할 사항이 있다. 멀티 쓰레드 환경에서 하나 이상의 객체가 생성되는 현상이 발견된다는 것이다.

이 현상을 어디서 접하게 되었는고 하니... Tomcat 기반의 웹 어플리케이션을 개발하면서 Singleton 패턴으로 커넥션풀 라이브러리를 만들어 두었다. 여러분도 알다시피 Tomcat에는 클래스파일이 변경되었는지 자동으로 감지하는 "Watch Dog" 이라는 기능이 탑재되어 있어서, 클래스의 변경을 감지하여 웹 어플리케이션(컨텍스트)을 다시 로딩하는 작업을 수행한다. 당시 데이터베이스의 커넥션 자원을 너무 많이 소모하는 것 같아서 디버깅 작업에 착수하였는데, WatchDog에 의하여 클래스를 다시 로딩할 때 Singleton 패턴으로 정의한 클래스의 객체가 여러 개 생겼음을 발견하게 되었다!!!

당연히 Singleton 패턴을 사용하면 같은 JVM 상에서는 오직 하나만 존재할 것으로 생각했던 내게 큰 충격이 아닐 수 없었다. 하여 문제를 해결하고자 검색해보니 멀티 쓰레드 환경에서 이런 문제가 꽤나 자주 있었음을 알 수 있었으며, 다음의 두 아티클을 찾을 수 있었다. 이 글들은 Java에서의 Singleton 패턴 구현 방식에 대하여 가장 잘 정리하고 있다:

http://www-106.ibm.com/developerworks/j ··· e%3Djava
http://c2.com/cgi/wiki?JavaSingleton

첫 번째 자료는 IBM 에 게시된 자료인데 그냥 참고로 읽고, 주로 두 번째 자료를 숙독하기 바란다. 내가 두 번째 자료를 접했을 당시에는 아래와 같은 해결책이 제시되어 있었다.

public class Singleton {
// final 키워드를 사용한 것에 주의할 것!
private static final Singleton _theInstance = new Singleton();

private Singleton() {
}

// synchronized 키워드가 사용되지 않았다는 점도 눈여겨 보자
public static Singleton getInstance() {
return _theInstance;
}
}

위 해결책은 Darren Hobbs 가 제안한 방법으로 Java Spec에 근거하여 제시한 방법이다. 하지만 Adam 은 이 방식이 거의 대부분의 상황에 잘 적용되긴 하지만 Tomcat 과 JBoss 두 컨테이너에서 테스트 해보니 생성자(constructor)에서 멤버 변수를 초기화하지 못하는 문제가 발견되었다고 문제를 제기하였다.

최근에 다시 두 번째 링크를 방문해 본 결과, Josh Bloch의 "Effective Java" 책 저술작업에 기여했던 Scot Floess 라는 사람이 David Geary가 JavaWorld에 게재한 글에 대해 Thread-safety 문제를 지적하며 제시한 해결책을 접할 수 있었다(※ 참고 : http://www.javaworld.com/javaworld/jw-0 ··· ers.html). 일단 Darren Hobbs 가 제안한 방법과 거의 같지만, 1) 클래스 선언 시 final 키워드를 붙여 상속이 불가능하도록 하였으며, 2) static 의 inner class를 사용하여 Singleton 패턴의 클래스를 감싸고 있는 형태가 다르다. 분명 이런 형태로 Singleton 패턴의 클래스를 생성하는 작업은 그 자체로 매우 무거운 작업이긴 하지만, 간단하면서도 완벽한 방식의 Singleton 패턴 구현 방식이라고 한다. 자세한 것은 링크를 참고하도록 하자.

/*
* final 키워드를 사용하여 이 클래스로부터 상속이 불가능하도록 하였다.
*/
public final class Singleton {
// static inner class (여기도 final 키워드 사용) 를 사용하여 Singleton 클래스의
// 객체를 생성함
private static final class SingletonHolder {
// 역시 이 내부에서도 static final 키워드 사용
static final Singleton singleton = new Singleton();
}

private Singleton() {}

public static Singleton getInstance() {
return SingletonHolder.singleton;
}
}

Trackback 0 Comment 0

Trackback : http://reme.tistory.com/trackback/287