2017-11-06 24 views
1

Double-checked Locking에 대해 article을 읽었습니다.Double-checked Locking (DCL) 및이를 수정하는 방법

public class MyFactory { 
    private static final MyFactory instance; 

    static { 
     try { 
      instance = new MyFactory(); 
     } catch (IOException e) { 
      throw new RuntimeException("Darn, an error's occurred!", e); 
     } 
    } 

    public static MyFactory getInstance() { 
     return instance; 
    } 

    private MyFactory() throws IOException { 
     // read configuration files... 
    } 
} 

저자는 말한다 : 모든 getInstance() 전화에 동기화를 방지하는 방법을 제안 된 방법의

public class MyFactory { 
    private static MyFactory instance; 

    public static synchronized MyFactory getInstance() { 
     if (instance == null) 
      instance = new MyFactory(); 
     return instance; 
    } 

    private MyFactory() {} 
} 

하나는 클래스 로더를 사용하는 것입니다 : 다음과 같이 설명 된 문제 "... JVM을 이 정적 초기화 코드는 클래스가 처음 참조되고로드 될 때 정확히 한 번 호출됩니다. " 나는 완전히 동의한다. 그러나 나는 다음을 이해하지 못한다. "클래스 로더를 사용하는 것이 일반적으로 게으른 정적 초기화를 다루는 선호하는 방법입니다."

두 번째 코드 스 니펫은 정적 정적 초기화입니까?

+0

우선이 질문에 제공된 예제는 전체 검사가 동기화되므로 이중 검사 잠금을 생성하지 않습니다.나는 당신이 여기에서 문제를 먼저 이해해야한다는 것을 두려워합니다. https://www.javamex.com/tutorials/double_checked_locking.shtml –

+0

@LyjuIEdwinson 첫 번째 코드 스 니펫은이 컨텍스트에서 문제입니다. 인용문 : "... 일부 프로그래머는 모든 읽기에서 동기화 된 액세스 및 "동기화가 느립니다". 그리고 Double-Check Locking은 내가 아는 한 그 해결책 중 하나입니다. –

+1

더 간결하게하기 위해 첫 번째 코드 단편은 해결해야 할 문제입니다. 그것은'getInstance()'의 모든 호출에서 동기화가 수행되기 때문에 느립니다. 'getInstance()'의 모든 호출에서 동기화를 피하는 한 가지 방법은 이중 검사 잠금 방지 패턴을 사용하는 것입니다. 또 다른 방법은 두 번째 코드 스 니펫을 사용하는 것입니다. [article] (https://www.javamex.com/tutorials/double_checked_locking_fixing.shtml)은 두 번째 코드 스 니펫이 지연 정적 초기화라고 주장합니다. 나는 그것이 왜 정적 인 초기 초기화인지 이해하지 못한다. –

답변

1

정확하게는 아닙니다. MyFactory 클래스가로드 될 때 초기화가 수행되고 getInstance()이 호출되지 않을 때 초기화가 수행됩니다. 메서드가 호출 될 때 인스턴스를 초기화하려면 홀더 클래스를 사용할 수 있습니다.

public class MyFactory { 
    private static final class Holder { 
     private static final MyFactory instance = new MyFactory(); 
    } 

    public static MyFactory getInstance() { 
     return Holder.instance; 
    } 
} 
2

게으른 것이 아닙니다. 이것은 게으른 것입니다 (클래스 로더 사용) :

1

두 번 선택 잠금은 놀고있는 것과 같습니다. 많은 사람들이 잘못 이해할 수있는 방법이 많이 있습니다.

이중 확인 잠금 관용구의 목적은 불필요한 synchronization을 피하기위한 것입니다. 따라서 첫 번째 코드 스 니펫은 카테고리에 맞지 않습니다. 작성중인 싱글이 static 경우

는 두 번째 코드에오고, 다음, 같은 클래스의 별도의 클래스하지에 static 필드로 싱글을 정의 할 수있는 컴팩트 한 솔루션이있다.

class MyFactorySingleton { 
    static MyFactory singleton = new MyFactory(); 
} 

자바의 이러한 의미는 필드가 참조 될 때까지 필드가 초기화되지 않습니다 보장, 그리고 필드가 해당 필드를 초기화 인한 쓰기를 모두 볼에 액세스하는 모든 스레드.

그러나 JDK5 이상에서

는, 자바는 말한다 volatile 의미를 지원하기 시작했다 그

volatile이 캐시 스레드 로컬 없을 것 선언 된 변수의 값. 모든 읽기 및 쓰기는 "메인 메모리"로 바로 이동합니다. 변수에 대한 액세스는 동기화 된 블록 에 묶여있는 것처럼 작동하며 자체적으로 동기화됩니다. 그래서

하는 일부 증거 어떤 바보 디자인 더블 - 확인과 같아야 찾고 :

class MyFactory { 
    private volatile MyFactory instance = null; 

    public MyFactory getInstance() { 
    if(instance == null) { 
     synchronized(MyFactory.class) { 
      if(instance == null) { 
       instance = new MyFactory(); 
      } 
     } 
    } 
    return instance; 
    } 
} 

교수 여호수아 블로흐와 그의 공동 저자는 두 번 확인 잠금이 잘못 될 수있는 방법을 설명합니다 이 article에 있습니다. 이것을 읽을만한 가치가 있습니다.