자바 Volatile 응용 단일 모드 구현 프로 세 스 분석
단선 에서 의 단일 모드 코드 를 돌 이 켜 보 세 요.
굶 주 린 사람 식
public class sington(){
  public final static INSTANCE = new singleton();
  private singleton(){}
}매 거 유형:이 유형의 대상 이 유한 하 다 는 것 을 나타 내 는 몇 가지 유형
우 리 는 한 개 로 한정 할 수 있 는데,단 례 라 고 부른다
public enum Singleto{
  INSTANCE
}
public class Singleton{
public final static INSTANCE;
static{
  INSTANCE = new Singleton();
}
private Singleton(){}
}이 유일한 인 스 턴 스 를 정적 변수 로 저장 합 니 다.
이 인 스 턴 스 를 가 져 오 는 정적 방법 을 제공 합 니 다.
public class Singleton{
  private static Singleton INSTANCE;
  private Singleton(){}
  public static Singleton getInstance(){
    if(instance==null){
      INSTANCE = new Singleton();
    }
    return INSTANCE;
  }
}
public class SingletonDemo {
  private static SingletonDemo instance = null;
  private SingletonDemo () {
    System.out.println(Thread.currentThread().getName() + "\t       SingletonDemo");
  }
  public static SingletonDemo getInstance() {
    if(instance == null) {
      instance = new SingletonDemo();
    }
    return instance;
  }
  public static void main(String[] args) {
    //     ==        
    System.out.println(SingletonDemo.getInstance() == SingletonDemo.getInstance());
    System.out.println(SingletonDemo.getInstance() == SingletonDemo.getInstance());
    System.out.println(SingletonDemo.getInstance() == SingletonDemo.getInstance());
    System.out.println(SingletonDemo.getInstance() == SingletonDemo.getInstance());
  }
} 
 그러나 다 중 스 레 드 환경 에서 우리 의 단일 모델 은 같은 대상 입 니까?
public class SingletonDemo {
  private static SingletonDemo instance = null;
  private SingletonDemo () {
    System.out.println(Thread.currentThread().getName() + "\t       SingletonDemo");
  }
  public static SingletonDemo getInstance() {
    if(instance == null) {
      instance = new SingletonDemo();
    }
    return instance;
  }
  public static void main(String[] args) {
    for (int i = 0; i < 10; i++) {
      new Thread(() -> {
        SingletonDemo.getInstance();
      }, String.valueOf(i)).start();
    }
  }
} 
 해결 방법
synchronized 키워드 도입
public synchronized static SingletonDemo getInstance() {
  if(instance == null) {
    instance = new SingletonDemo();
  }
  return instance;
} 
 Synchronized 키 워드 를 도입 함으로써 높 은 병발 환경 에서 의 단일 모델 문 제 를 해결 할 수 있 음 을 알 수 있 습 니 다.
그러나 synchronized 는 중량급 동기 화 체제 로 하나의 스 레 드 만 동시에 방문 하여 인 스 턴 스 를 얻 는 방법 을 허용 하지만 데이터 의 일치 성 을 확보 하기 위해 동시성 을 낮 추 었 기 때문에 사용 하 는 것 이 비교적 적다.
해결 방법
DCL Double Check Lock 양단 잠 금 메커니즘 도입 을 통 해
  public static SingletonDemo getInstance() {
    if(instance == null) {
      //         ,    
      synchronized (SingletonDemo.class) {
        if(instance == null) {
          instance = new SingletonDemo();
        }
      }
    }
    return instance;
  } 
 출력 결 과 를 보면 단일 모델 의 정확성 을 확보 할 수 있 지만 위의 방법 에는 문제 가 존재 한다.
DCL(양단 검 쇄)메커니즘 이 반드시 라인 이 안전 한 것 은 아니다.왜냐하면 지령 재배 열 이 존재 하기 때문이다.volatile 에 가입 하면 지령 재배 열 을 금지 할 수 있다
이 유 는 한 스 레 드 가 첫 번 째 검 측 을 실 행 했 을 때 인 스 턴 스 가 null 이 아 닌 것 을 읽 었 기 때 문 입 니 다.인 스 턴 스 의 참조 대상 이 실례 화 되 지 않 았 을 수도 있 습 니 다.왜냐하면 instance=new SingletonDemo();다음 세 단계 로 나 누 어 완성 할 수 있 습 니 다.
즉,리 셋 후 단계 2 를 실행 하고 인 스 턴 스 를 가 져 오 려 고 할 때 null 을 얻 을 수 있 습 니 다.대상 의 초기 화가 완료 되 지 않 았 고 리 셋 후 단계 3 이 완성 되 었 기 때문에 단일 모드 의 코드 를 실행 할 때 인 스 턴 스 인 스 턴 스 인 스 턴 스 를 다시 만 듭 니 다.
명령 정렬 은 직렬 의미 의 집행 일치 성(단일 스 레 드)만 보장 하지만 다 중 스 레 드 간 의 의미 일치 성 은 관계 되 지 않 습 니 다.
따라서 하나의 스 레 드 가 intance 에 접근 하지 않 을 때 intance 인 스 턴 스 가 초기 화 되 지 않 았 기 때문에 스 레 드 안전 에 문제 가 생 겼 습 니 다.
따라서 volatile 을 도입 하여 명령 재배 치 문제 가 발생 하도록 하고 단일 모델 의 스 레 드 안전성 을 확보 해 야 한다.
private static volatile SingletonDemo instance = null;
최종 코드
public class SingletonDemo {
  private static volatile SingletonDemo instance = null;
  private SingletonDemo () {
    System.out.println(Thread.currentThread().getName() + "\t       SingletonDemo");
  }
  public static SingletonDemo getInstance() {
    if(instance == null) {
      // a                            ,             d 
      synchronized (SingletonDemo.class) //b
      { 
      //c  volitale                         。             
        if(instance == null) { 
        	// d         
          instance = new SingletonDemo();
        }
      }
    }
    return instance;
  }
  public static void main(String[] args) {
//    //     ==        
//    System.out.println(SingletonDemo.getInstance() == SingletonDemo.getInstance());
//    System.out.println(SingletonDemo.getInstance() == SingletonDemo.getInstance());
//    System.out.println(SingletonDemo.getInstance() == SingletonDemo.getInstance());
//    System.out.println(SingletonDemo.getInstance() == SingletonDemo.getInstance());
    for (int i = 0; i < 10; i++) {
      new Thread(() -> {
        SingletonDemo.getInstance();
      }, String.valueOf(i)).start();
    }
  }
}이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
JPA + QueryDSL 계층형 댓글, 대댓글 구현(2)이번엔 전편에 이어서 계층형 댓글, 대댓글을 다시 리팩토링해볼 예정이다. 이전 게시글에서는 계층형 댓글, 대댓글을 구현은 되었지만 N+1 문제가 있었다. 이번에는 그 N+1 문제를 해결해 볼 것이다. 위의 로직은 이...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.