GOF 23 학습 노트 (2) 왜 단일 모드 에서 이중 검사 자물쇠 에 결함 이 있 습 니까?
2976 단어 디자인 모드
public static Singleton3 getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
이 방법 은 동기 화 된 내용 을 if 내부 로 이동 시 켜 처음 만들어 야 동기 화 되 고 효율 을 높 일 수 있 습 니 다.그러나 이 방법 은 명령 의 정렬 에 영향 을 받는다.
지령 재 정렬: 지령 재 정렬 은 지령 을 최적화 하고 프로그램의 운행 효율 을 높이 기 위 한 것 이다.명령 재 정렬 은 컴 파일 러 의 재 정렬 과 실행 시 재 정렬 을 포함한다.JVM 규범 에 따 르 면 명령 재 정렬 은 단일 스 레 드 프로그램의 실행 결과 에 영향 을 주지 않 는 전제 에서 진행 할 수 있다.예컨대 instance = new Singleton () 은 다음 과 같은 위조 코드 로 분해 할 수 있 습 니 다.
memory = allocate(); //1:
ctorInstance(memory); //2:
instance = memory; //3: instance
근 데 지령 을 받 고 정렬 을 다시 하면 이렇게 돼 요.
memory = allocate(); //1:
instance = memory; //3: instance
// , !
ctorInstance(memory); //2:
이렇게 하면 문제 가 발생 할 수 있 습 니 다. 스 레 드 A 가 intance = memory () 를 실 행 했 습 니 다. 이 단 계 는 스 레 드 B 를 볼 수 있 습 니 다. 그러면 스 레 드 B 가 if (intance = = null) 를 판단 할 때 intance 가 비어 있 지 않 은 것 을 발견 하고 intance 로 돌아 갑 니 다. 그러나 intance 는 내 장 된 주 소 를 가리 키 기 때문에 실제 초기 화 되 지 않 았 습 니 다.그러면 스 레 드 B 는 완전히 초기 화 되 지 않 은 인 스 턴 스 를 되 돌려 줍 니 다.
이중 검출 잠 금 수정판
따라서 수정판 에 서 는 두 개의 동기 블록 에 국부 변 수 를 추가 하여 이 문 제 를 해결 하려 고 합 니 다. 먼저 동기 블록 으로 국부 변 수 를 초기 화하 고 완전히 초기 화 한 후에 인 스 턴 스에 값 을 부여 하여 인 스 턴 스 가 완전히 초기 화 되 었 음 을 보증 합 니 다.
public class Singleton3 {
private static Singleton3 instance = null;
private Singleton3() {};
public static Singleton3 getInstance() {
if(instance == null) {
Singleton3 sc;
synchronized (Singleton3.class) {
sc = instance;
if(sc == null) {
synchronized (Singleton3.class) {
if(sc == null) {
sc = new Singleton3();
}
}
instance = sc;
}
}
}
return instance;
}
}
그러나 이런 방법 은 여전히 문제 가 존재 합 니 다. 자바 는 동기 블록 안의 내용 을 대상 잠 금 이 풀 리 기 전에 실행 해 야 한다 고 규정 하고 있 습 니 다. (즉, 하나의 스 레 드 가 실행 되 어야 다른 스 레 드 가 실 행 될 수 있 습 니 다) 그러나 동기 블록 이외 의 코드 는 규정 되 어 있 지 않 습 니 다. 동기 블록 이 실 행 된 후에 실행 해 야 한 다 는 것 을 의미 합 니 다.instance = sc 운행 과정 에서 내부 동기 블록 으로 달 려 갈 가능성 이 높다.이렇게 해서 명령 을 다시 정렬 하 는 문제 가 다시 발생 했 습 니 다. 즉, sc 가 메모리 주 소 를 가리 키 고 초기 화 되 지 않 았 을 때 인 스 턴 스 에 값 을 부여 하여 외부 스 레 드 가 완전히 초기 화 되 지 않 은 인 스 턴 스 를 직접 얻 었 습 니 다.
JDK 1.5 이후, volatile 변 수 를 사용 하여 DCL 을 유효 하 게 정렬 하 는 명령 을 금지 할 수 있 습 니 다.
public class Singleton3 {
// volatile
private static volatile Singleton3 instance;
private Singleton3() {
}
public static Singleton3 getInstance() {
if (instance == null) {
synchronized (Singleton3.class) {
if (instance == null) {
instance = new Singleton3();
}
}
}
return instance;
}
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
디자인 모델 의 공장 모델, 단일 모델자바 는 23 가지 디자인 모델 (프로 그래 밍 사상/프로 그래 밍 방식) 이 있 습 니 다. 공장 모드 하나의 공장 류 를 만들어 같은 인 터 페 이 스 를 실현 한 일부 종 류 를 인 스 턴 스 로 만 드 는 것...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.