자바 동시성 노트 - 싱글 및 듀얼 감지

에서 전송 자바 동시성 노트 - 싱글 및 듀얼 감지

싱글 패턴은 클래스의 한 객체 인스턴스는이 오브젝트 공간 오버 헤드를 생성하기 위해 주파수 및 시간을 감소시킬 수 있도록 할 수있다. 다음과 같이 단일 스레드 모드는 일반적인 단일 모드 코드의 예이다 :

class Singleton{
    private static Singleton singleton;    
    private Singleton(){}
    
    public static Singleton getInstance(){
        if(singleton == null){
            singleton = new Singleton();   //1
        }
        return singleton;
    }
}

외부 세계 만의 getInstance () 메소드를 통해 예를 얻기 위해, 싱글 톤 클래스 생성자에 의해 인스턴스화 할 수 없도록 생성자 개인. 이 개체를 필요한 경우에만 작동 인스턴스화 게으른 로딩 버전입니다. 이 방법은 단일 스레드에서 제대로 작동하지만 동기화 방법이 없기 때문에 상황은 다중 스레드 환경에서 나타날 것보다 단일 객체로 이어집니다. 그 이유는 다음 (1) // 수행있을 수 있습니다 동안 두 개의 스레드 A와 B가 동시에 조건문 경우 수행되는 것입니다 빈 그래서, B도 결정 싱글이 비어있는 1 개 // CPU의 타임 슬라이스를 수행 할 준비가 결정 싱글입니다 이 때, 상기 오브젝트의 인스턴스를 생성, 상기 CPU 시간 슬라이스를 얻은 후 다음 단일 개체 실시하는 복수의 리드 오브젝트의 인스턴스를 생성 // 1 행한다.

문제에 대한 해결 방법은 동기화 된 키워드를 사용하여 간단하다 :

class Singleton{
    private static Singleton singleton;    
    private Singleton(){}
    
    public static synchronized Singleton getInstance(){
        if(singleton == null){
            singleton = new Singleton();    //1
        }
        return singleton;
    }
}

이 동시 멀티 스레드 만 가져왔다 효율성의 문제를 해결한다 : 우리의 목표는 오직 하나의 인스턴스를 생성하는 것입니다, 즉 // 1 단지 동기화 할 필요가 이쪽 번만 실행되고, 뒤쪽의 인스턴스를 생성 이후, 싱글 직접 null이 아닌 객체 참조를 반환 할 수 있지만 비어 있지 않은 모든 동기 코드 검증 차단합니다. 그것은 단지 1 // 동기화로 간주 될 수 있습니다 :

class Singleton{
    private static Singleton singleton;    
    private Singleton(){}
    
    public static Singleton getInstance(){
        if(singleton == null){
            synchronized(Singleton.class){                
                singleton = new Singleton();   //1
            }
        }
        return singleton;
    }
}

이, 여러 스레드가 동시에 조건문을 실행하는 첫 번째 질문과 동일하게 나타납니다 때, 여러 인스턴스를 생성합니다. 문제는 인스턴스 후 스레드가 생성 될 때, 싱글이 더 이상 비어 있지만, 두 번째 검사를하지 않는 후속 스레드가 비어 있지 않은지 없습니다. 동기화 코드 블록을 다시 소위 더블 탐지를 확인해야합니다 분명하다 :

이중 탐지 (더블 체크) :

class Singleton{
    private static Singleton singleton;    
    private Singleton(){}
    
    public static Singleton getInstance(){
        if(singleton == null){
            synchronized(Singleton.class){
                if(singleton == null)
                    singleton = new Singleton();   //1
            }
        }
        return singleton;
    }
}

여기 아무 문제가없는 것, 완벽했다. 그러나 JDK1.5 전에이 두 배 감지 메커니즘은 문제가, 문제가 계속 발생하는 소위 장애에 의해 작성, // 1에있다. 경험의 메모리 할당이 초기화, 힙의 일련의 동작에 객체 참조를 반환 할 때 오브젝트가 초기화 될 때, 일반적으로, 완전한 목적이 방법으로 생성 된 오브젝트는 일반적으로 사용할 수있다. 그러나 JAVA 쓰기 장애, 역순, 즉, 메모리 할당 결과이 경우 널이 아닌 1 개 // 싱글 톤에 대응하는 오브젝트 참조, 초기화 시퀀스를 반환 할 수 있지만, 힙의 객체 포인트 하지만 개체가 여전히 초기화 작업을 완료되지 않습니다. 후속 싱글 스레드 예기치 않은 문제가 발생했을 때 직접 사용되지 널 발견합니다.

JDK1.5 후에는 문제가 휘발성 키워드에 중요한 역할을 객체 참조를 반환하지 보장 명령 재 배열, 메모리 할당을 금지하기 때문에, 작성 순서가 발생을 해결하기 위해 수정 변수 휘발성 키워드를 사용할 수 있습니다, 같은 초기화 순서, 이중 감지 정말 작동 할 수 있도록. 물론, 당신은 또한 이중 감지 및 같은 효과를 달성하기 위해 비 지연 로딩 방식을 사용하지 않도록 선택할 수 있습니다 :

class Singleton{
    private static Singleton singleton = new Singleton();    
    private Singleton(){}
    
    public static Singleton getInstance(){
        return singleton;
    }
}

추천

출처blog.csdn.net/weixin_43115440/article/details/90480272