Java 구현 단일 모드

6195 단어 Android
정의
단례 모델은 단자 모델이라고도 부르며 자주 사용하는 소프트웨어 디자인 모델이다.이 모델을 응용할 때, 단일 대상의 클래스는 반드시 하나의 실례만 존재할 것을 보장해야 한다.많은 경우 전체 시스템은 하나의 전체적인 대상만 가지면 시스템 전체의 행위를 조율하는 데 유리하다.예를 들어 어떤 서버 프로그램에서 이 서버의 설정 정보는 하나의 파일에 저장되고 이러한 설정 데이터는 하나의 단일 대상이 통일적으로 읽은 다음에 서비스 프로세스의 다른 대상이 이 단일 대상을 통해 이러한 설정 정보를 얻는다.이런 방식은 복잡한 환경에서의 배치 관리를 간소화시켰다[1].(wiki)
빌드 모드
일반적으로 우리는 두 가지 방식으로 하나의 예를 세울 수 있다.
게으름뱅이 방식: 전역적인 실례가 처음 사용될 때 구축되는 것을 가리킨다.
굶주린 사람 방식: 전체 국면의 단일 사례가 클래스를 불러올 때 구축되는 것을 가리킨다.
구축 코드
게으름뱅이식(라인이 안전하지 않음)
public class Singleton {
    private static Singleton INSTANCE = null;

    private Singleton() {
    }

    public static Singleton getInstance() {
        if (INSTANCE == null)
            INSTANCE = new Singleton();
        return INSTANCE;
    }
}

장점은 이해하기 쉽다는 것이고, 단점은 다선정에서 두 가지 실례가 나올 수 있다는 것이다.
게으름뱅이식(라인 안전)
public class Singleton {
    private static Singleton INSTANCE = null;

    private Singleton() {
    }

    public static synchronized Singleton getInstance() {
        if (INSTANCE == null)
            INSTANCE = new Singleton();
        return INSTANCE;
    }
}

장점은 라인이 안전하다는 것이다. 단점은 효율이 낮다는 것이다. 매번 하나의 실례를 얻을 때마다 자물쇠를 채워야 한다. 자물쇠를 채워야 하는 것은 매우 많은 시간을 소모하는 작업이기 때문에 필요하지 않을 때 우리는 가능한 한 피해야 한다.
게으름뱅이형(DCL: 이중 잠금)
public class Singleton {
    private static Singleton INSTANCE = null;

    private Singleton() {
    }

    public static synchronized Singleton getInstance() {
        if (INSTANCE == null) {
            synchronized (Singleton.class) {
                if (INSTANCE == null) {
                    INSTANCE = new Singleton();
                }
            }
        }
        return INSTANCE;
    }
}

외국인들은 이런 문법에 대해 Clever, but broken DCL은 이론적으로 빈틈이 없지만 실제로 현실 세계는 그렇지 않다고 평가한다.DCL은 단일 또는 다중 프로세서 시스템의 작동을 보장할 수 없습니다.DCL 실패의 문제는 JVMs의 버그가 아니라 현재 Java 플랫폼의 메모리 모델입니다.메모리 모델은'out-of-order writes'의 존재를 허용하고 DCL 실패의 주범이다[2].
out-of-order writes
전체 문제의 관건은 INSTANCE = new Singleton ()에서 나온다.이 코드는 다음 세 단계로 나눌 수 있습니다.
mem = allocate();           // Singleton         
INSTANCE = mem;             //   INSTANCE    null,          
ctorSingleton(instance);     //  Singleton     

두 번째 단계까지 실행할 때 메모리가 분배되었고 인스타그램 인용도 새로운 분배 메모리를 가리키며 구조 함수는 아직 실행되지 않았습니다.이때 다른 라인이 체크인스턴트에 왔을 때 이 인스턴트가 null이 아닌 것을 발견하고 동기화 블록을 넘어서 인스턴트가 인용한 구조의 절반을 되돌려준다.이것이 DCL 실패의 원인[2]입니다.
인터넷상에서 일부 글은volatile 키워드를 통해 인스타그램을 수식할 수 있어 DCL이 정상적으로 작동할 수 있다고 하지만 외국의 글을 보면volatile에도 다른 문제가 생길 수 있다[2][3].
굶주림식(static final)
public class Singleton {
    private final static Singleton INSTANCE = new Singleton();

    private Singleton() {
    }

    public static Singleton getInstance() {
        return INSTANCE;
    }
}

정적 내부 클래스
public class Singleton {
    private static class SingletonHolder {
        private static final Singleton INSTANCE = new Singleton();
    }

    private Singleton() {
    }

    public static Singleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
}

정적 내부 클래스는 처음 사용할 때 불러오기 때문에 게으름뱅이식이고 이 실현 과정에 자물쇠가 없기 때문에 성능에서도 좋은 효과를 얻을 수 있으며 JVM은 라인 안전을 보장한다.
아사자식(매거)
public enum EasySingleton{
    INSTANCE;
}

참고 문헌
1.https://zh.wikipedia.org/wiki/%E5%8D%95%E4%BE%8B%E6%A8%A1%E5%BC%8F 2.http://www.ibm.com/developerworks/library/j-dcl/ 3.http://www.javaworld.com/article/2074979/java-concurrency/double-checked-locking–clever–but-broken.html

좋은 웹페이지 즐겨찾기