Singleton Pattern 과 DeadLock

by 조쉬 posted Feb 15, 2023
?

단축키

Prev이전 문서

Next다음 문서

ESC닫기

크게 작게 위로 아래로 댓글로 가기 인쇄

싱글톤 패턴: 하나의 인스턴스만 사용하기 위한 디자인 패턴, 스레드 풀링, 커넥션 풀링 등에서 주로 사용합니다.

  1.  인스턴스를 생성할 때 참조 변수를 private static으로 합니다. 
  2. 생성자를 private로 한다. 이는 외부에서 new로 인스턴스를 생성하지 못하게 합니다.
  3. 인스턴스를 리턴하는 public static getInstance() 메서드를 제공합니다. 이 메서드 내부에서 인스턴스를 생성할 때 null 체크 후 생성해서 인스턴스를 리턴 해야 합니다.
  4. 멀티스레드 환경에서는 위 getInstance메서드를 synchronized 해야 안전합니다. 하지만 전반적인 성능 저하 때문에 일반적으로 아래와 같은 패턴으로 코딩합니다.
싱글톤패턴1
public class InitializationOnDemandHolderIdiom {
 
 private InitializationOnDemandHolderIdiom () {}
 private static class Singleton {
  private static final InitializationOnDemandHolderIdiom instance = new InitializationOnDemandHolderIdiom();
 }
 
 public static InitializationOnDemandHolderIdiom getInstance () {
  System.out.println("create instance");
  return Singleton.instance;
 }
}

싱글톤패턴2

public enum EnumInitialization {
 INSTANCE;
 static String test = "";
 public static EnumInitialization getInstance() {
  test = "test";
  return INSTANCE;
 }
}


 

멀티스레드 Deadlock 방지를 위한 고려 사항들
  • 멀티스레드에서 내부에서 호출하는 메서드 중에서 인스턴스의 멤버 변수에 접근할 때는 synchronized 해주어야한다.
  • 멀티스레드 환경에서는 singleton 패턴으로 인스턴스를 하나만 생성해서는 병목현상이 일어나므로 되도록 singleton 패턴을 안 쓰는 것이 좋다.
  • 서블릿 프로그램에서 서블릿 클래스에 멤버 변수를 정의하지 말라. 서블릿 인스턴스는 컨테이너에서 싱글톤 처럼 동작(한 번 생성한 인스턴스를 재활용)하므로 스레드 경합시 데이터 값을 보장할 수 없기 때문이다.
  • 오픈 호출: lock을 확보하지 않은 상태로 메서드 호출 하는 기법
  • lock의 시간제한: 암묵적인 락 synchronized 말고 락 시간을 제한할 있는 Lock 클래스의 tryLock 메소드를 사용한다. 
  • 순환대기 (circular wait) 예방 : 프로그래밍에서 적용할 수 있는 현실적인 방법이다. 여러가지 아이디어가 있을 수 있지만 핵심은 lock을 걸어주는 타이밍을 잘 조정해 주어서 순환 대기가 발생하지 않게 하는 것이다.
  • synchronized 동기화 블록 최소화
 
 
 
 
참고 URL

https://blog.seotory.com/post/2016/03/java-singleton-pattern