ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Design Pattern] Singleton Pattern
    Programming/DesignPattern 2020. 12. 14. 20:07
    • 싱글턴 패턴의 이해
    • 멀티 쓰레드 환경에서 싱글턴 패턴

     

    싱글턴 패턴은 인스턴스가 오직 하나만 생성되는 것을 보장하고 어디에서든 이 인스턴스에 접근할 수 있도록 하는 디자인 패턴이다.

     

    *Singleton: 하나의 인스턴스만을 생성하는 책임이 있으머, getInstance() 메서드를 통해 모든 클라이언트에게 동일한 인스턴스를 반환하는 작업 수행한다.

     

     

    public class Printer {
    	private static Printer printer = null;
        
        public static Printer getPrinter() {
        	if (printer == null)
            	printer = new Printer();
            return printer;
        }
    }

    위 코드를 보면, printer 변수와 getPrinter() 메서드를 static으로 선언하여 어디에서든지 참조할 수 있도록 했다.

     

    위의 코드는 다중 스레드 환경에서 문제가 발생할 수 있다. 다중 스레드에서 Printer 클래스를 이용할 때 인스턴스가 1개 이상 생성되는 경우가 발생할 수 있다.

    1. Printer 인스턴스가 아직 생성되지 않았을 때, 쓰레드1이 getPrinter() 메서드의 if문을 실행해 이미 인스턴스가 생성되었는지 확인한다. 현재 printer 변수는 null 인 상태이다.
    2. 만약 쓰레드1이 생성자를 호출해 인스턴스를 만들기 전, 쓰레드2가 if문을 실행해 printer 변수가 null인지 확인한다. 현재 null 이므로 인스턴스를 생성하는 코드, 즉 생성자를 호출하는 코드를 실행하게 된다.
    3. 쓰레드1도 쓰레드2와 마찬가지로 인스턴스를 생성하는 코드를 실행하게 되면 결과적으로 Printer 클래스의 인스턴스가 2개가 생성된다.

    이는 경합조건(Race Condition)을 발생시킨다. 경합 조건이란 메모리와 같은 동일한 자원을 2개 이상의 쓰레드가 이용하려고 경합하는 현상을 말한다.

     

     

    해결책

    • 정적 변수에 인스턴스를 만들어 바로 초기화하는 방법
      • static 변수는 객체가 생성되기 전 클래스가 메모리에 로딩될 때 만들어져 초기화가 한 번만 실행된다. 또한 static 변수는 프로그램 실행부터 종료까지 없어지지 않고, 메모리에 상주하며 클래스에서 생성된 모든 객체에서 참조할 수 있다.
    • 인스턴스를 만드는 메서드에 동기화하는 방법
      • 다중 스레드 환경에서 여러 스레드가 getPrint() 메서드를 소유하는 객체에 접근하는 것을 방지한다. 결과적으로 Printer 클래스의 인스턴스가 오직 하나의 인스턴스만 생성한다.,
      • 해당 클래스에 선언된 정적변수에 접근하는 부분도 synchronized 키워드를 사용하여 동기화 시켜야한다.
      • 여러 쓰레드가 하나뿐인 counter 변수 값에 동시에 접근해 갱신할 수 있기 때문이다. 

     

    public class HSPrinter520 implements Printer{
        private static Printer printer = null;
        private HSPrinter520(){}
    
        public synchronized static Printer getPrinter(){
            if (printer != null){
                printer = new HSPrinter520();
            }
            return printer;
        }
    
        @Override
        public void print(String str) {
            System.out.println(str);
        }
    }

     

    정적 클래스를 이용하는 방법이 싱글턴 패턴을 이용하는 방법과 가장 차이나는 점은 객체를 전혀 생성하지 않고 메서드를 사용한다는 점이다. 이는 실행될 때 바인딩되는 인스턴스 메서드를 사용하는 것보다 성능 면에서 우수하다고 할 수 있다.(?)

     

    그러나 정적 메서드는 인터페이스에서 사용할 수 없다. 즉, 정적메서드를 통해 싱글톤을 구현하는 경우, 인터페이스를 사용할 수 없기 때문에 테스트 환경에서 매우 불리하다고 한다.

    'Programming > DesignPattern' 카테고리의 다른 글

    [Design Pattern] Observer Pattern  (0) 2020.12.26
    [Design Pattern] Command Pattern  (0) 2020.12.17
    [Design Pattern] State Pattern  (0) 2020.12.15
    [Design Pattern] Strategy Pattern  (0) 2020.12.10
Designed by Tistory.