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

 

다음의 코드는 기본적인 Singleton방법이며 인스턴스가 필요할때 한번 생성한다. 하지만 JVM입장에서 생각했을때 한개 이상의 쓰래드가 실행된다고 가정해보면 동시에 하나이상의 쓰래드가  uniqueInstance변수가 null임을 체크하고 객체를 초기화 하는 과정에서 새로운 객체를 생성해서uniqueInstance변수에 할달 가능성이 있기때문에 Thread Safe하지 못하다.(Head first Design Pattern 참조)

 

package headfirst.singleton.classic;

 

/**

 * NOTE: This is not thread safe!

 *

 * @author Steven J.S Min

 *

 */

public class Singleton {

       private static Singleton uniqueInstance;

 

       // other useful instance variables here

 

       private Singleton() {

       }

 

       public static Singleton getInstance() {

              if (uniqueInstance == null) {

                     uniqueInstance = new Singleton();

              }

              return uniqueInstance;

       }

 

       // other useful methods here

}

 

 

 

인스턴스를 필요할 생성하지 않고 처음부터 만드는 방법

 

어플리케이션엣 반드시 Singleton 인스턴스를 생성하고, 인스턴스를 항상 사용한다면, 또는 인스턴스를 실행중에 수시로 만들고 관리하기가 성가시다면 다음과 같이 처음부터 Singleton인스턴스를 만들어 버리는 것도 괜찮은 방법이다.

 

 

package headfirst.singleton.stat;

 

public class Singleton {

       private static Singleton uniqueInstance = new Singleton();

 

       private Singleton() {}

 

       public static Singleton getInstance() {

              return uniqueInstance;

       }

}

 

 

 

Synchronized키워드를 이용한Singleton

 

Synchronized 속도가 그리 중요하지 않다면 그냥 사용해도 괜찮은 방법이기는 하지만 성능면에서는 100이상의 성능 저하가 발생할 있다는 것을 인식해야한다.

 

package headfirst.singleton.threadsafe;

 

public class Singleton {

       private static Singleton uniqueInstance;

 

       // other useful instance variables here

 

       private Singleton() {

       }

 

       public static synchronized Singleton getInstance() {

              if (uniqueInstance == null) {

                     uniqueInstance = new Singleton();

              }

              return uniqueInstance;

       }

 

       // other useful methods here

}

 

 

 

 

DLC(Double Checking Locking)을이용한Singleton

 

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

 

package headfirst.singleton.dcl;

 

/**

 * Danger! This implementation of Singleton not guaranteed

 * to work prior to Java 5

 *

 * @author Steven J.S Min

 *

 */

public class Singleton {

       private volatile static Singleton uniqueInstance;

 

       private Singleton() {

       }

 

       public static Singleton getInstance() {

              if (uniqueInstance == null) {

                     synchronized (Singleton.class) {

                           if (uniqueInstance == null) {

                                  uniqueInstance = new Singleton();

                           }

                     }

              }

              return uniqueInstance;

       }

}

 

 

 

** volatile키워드를 사용하면 멀티스레딩을 하더라도uniqueInstance변수가 singleton인스턴스로 초기화 되는 과정이 올바르게 진행되도록 있다. Java 5이전의 버전을 사용한다면 DCL방법의 사용은 사용하지 말자.

 

volatile이란 단어의 뜻은 "변덕스러운"이다. 다시 말하자면 "자주 변할 있다" 생각할 있다. 프로그래밍 언어에서는 정의는 언어와 버전마다 다르지만, 대충은 "자주 변할 있는 놈이니 있는 그대로 가져다써"정도로 생각을 하면 되겠다. 조금 엄밀히 정의를 하자면, (1) 특정 최적화에 주의해라, (2) 멀티 쓰레드 환경에서 주의해라, 정도의 의미를 준다고 보면 된다.

 

Java에서는 어떤 의미를 가질까? volatile 사용한 것과 하지 않은것의 차이는 뭘까? volatile 버전마다의 차이는 뭘까? synchronization volatile 차이는 뭘까? 의문들에 대해서 정리한 것은 다음과 같다.

 

ü  volatile 사용하지 않은 변수: 마구 최적화가 있다. 재배치(reordering) 수있고, 실행중 값이 캐쉬에 있을 있다.

ü  volatile 사용한 변수 (1.5미만): 변수 자체에 대해서는 최신의 값이 읽히거나 쓰여진다.

ü  volatile 사용한 변수 (1.5이상): 변수 접근까지에 대해 모든 변수들의 상황이 업데이트 되고, 변수가 업데이트된다.

ü  synchronziation 사용한 연산: synch블락 전까지의 모든 연산이 업데이트 되고, synch안의 연산이 업데이트된다.

 

 

'Java Design Pattern' 카테고리의 다른 글

Strategy 패턴 - 알고리즘을 사용하는 클라이언트와 독립적으로 구현  (0) 2013.02.20
Facade 패턴  (0) 2013.02.19
Adapter 패턴  (0) 2013.02.19
Command 패턴  (0) 2013.02.19
객체지향 설계의 원칙  (0) 2013.02.19
Posted by Steven J.S Min
,