Java Concurrent Programming (7)
5803 단어 Java다 중 스 레 드performanceJDKIDEA
7. Double-Checked Locking
이중 검사 잠 금 메커니즘 은 상투적인 문제 이다.이중 검사 잠 금 체 제 는 이미 광범 위 하 게 인용 되 었 으 며, 특히 다 중 스 레 드 환경 에서 의 게 으 른 로드 실현 에 있어 서 는.그러나 추가 동기 화가 없 으 면 자바 플랫폼 에서 독립 적 으로 실행 할 수 없습니다.이 코드 를 보십시오.
public class Singleton {
private Singleton instance = null;
public Singleton getInstance(){
if(instance == null){
instance = new Singleton();
}
return instance;
}
// other function
}
이 코드 가 다 중 스 레 드 환경 에서 실행 되면 많은 오류 가 발생 할 수 있 습 니 다.가장 눈 에 띄 는 것 은 싱글 턴 대상 이 두 번 이나 두 번 이상 예화 된다 는 점 이다.이 오 류 를 해결 하기 위해 서 는 getInstance () 방법 에 synchronized 키 워드 를 추가 하고 고 친 종 류 는 다음 과 같 습 니 다.
public class Singleton {
private Singleton instance = null;
public synchronized Singleton getInstance(){
if(instance == null){
instance = new Singleton();
}
return instance;
}
// other function
}
현재 getInstance () 방법 을 호출 할 때마다 동기 화 됩 니 다.이중 검사 잠 금 메커니즘 은 인 스 턴 스 가 null 이 아 닐 때 추가 동기 화 비용 이 발생 하지 않도록 코드 가 생 겼 습 니 다.
public class Singleton {
private Singleton instance = null;
public Singleton getInstance(){
if(instance == null){
synchronized(this){
if(instance == null){
instance = new Singleton();
}
}
}
return instance;
}
// other function
}
그러나 이 코드 가 최 적 화 된 컴 파일 러 나 공유 메모리 다 중 프로세서 가 존재 하 는 상황 에서 실행 된다 면 통 하지 않 습 니 다.주로 오래된 자바 메모리 모델 로 인해 getInstance () 방법 을 호출 한 후 비 어 있 는 인 스 턴 스 참조 가 보이 지만, singleton 의 모든 속성 은 구조 함수 에서 지정 한 값 이 아 닌 기본 값 입 니 다.컴 파일 러 가 구조 함수 가 이상 을 던 지지 않 거나 동기 화 를 실행 하지 않도록 보장 할 수 있다 면 컴 파일 러 내 연 된 구조 함수 가 호출 되 었 다 면 인 스 턴 스 와 모든 속성 을 초기 화 하 는 쓰기 작업 은 재 순 될 것 입 니 다.컴 파일 러 가 정렬 을 다시 하지 않 더 라 도 다 중 핵 처리 나 메모리 시스템 에서 정렬 을 다시 할 수 있 습 니 다.그래서 다음 과 같은 개선 이 있 었 다.
public class Singleton {
private Singleton instance = null;
public Singleton getInstance(){
if(instance == null){
Singleton s ;
synchronized(this){
s = instance;
if(s == null){
synchronized(this){
s = new Singleton();
} // release inner synchronization lock
}
instance = s;
}
}
return instance;
}
}
인용 하 다.
This code puts construction of the Singleton object inside an inner synchronized block. The intuitive idea here is that there should be a memory barrier at the point where synchronization is released, and that should prevent the reordering of the initialization of the Helper object and the assignment to the field helper.
Unfortunately, that intuition is absolutely wrong. The rules for synchronization don't work that way. The rule for a monitorexit (i.e., releasing synchronization) is that actions before the monitorexit must be performed before the monitor is released. However, there is no rule which says that actions after the monitorexit may not be done before the monitor is released. It is perfectly reasonable and legal for the compiler to move the assignment instance = s; inside the synchronized block, in which case we are back where we were previously. Many processors offer instructions that perform this kind of one-way memory barrier. Changing the semantics to require releasing a lock to be a full memory barrier would have performance penalties.
Alexander Terekhov 는 매우 교묘 한 문제 해결 방법 을 생각해 냈 고 ThreadLocal 변 수 를 통 해 이중 검사 잠 금 메커니즘 문 제 를 실현 했다.
public class Singleton {
/** If perThreadInstance.get() returns a non-null value, this thread
has done synchronization needed to see initialization
of helper */
private final ThreadLocal local = new ThreadLocal();
private Singleton instance = null;
public Singleton getInstance(){
if(local.get() == null){
createInstance();
}
return instance;
}
private final void createInstance(){
synchronized(this) {
if (instance == null)
instance = new Singleton();
}
local.set(instance);
}
// other function
}
이 코드 의 성능 은 JDK 의 실현 에 달 려 있다.JDK 1.2 에서 ThreadLocal 은 매우 느 려 서 1.3 이 뚜렷하게 향상 되 었 다.비록 이 코드 는 현재 로 서 는 잘못된 것 같 지만, 당시 에는 이중 검사 자물쇠 메커니즘 으로 인 한 문 제 를 확실히 해결 했다.
JDK 1.5 이후 새로운 자바 메모리 모델 과 스 레 드 규범 후 volitale 키 워드 를 통 해 읽 기와 쓰기 의 재 순 서 를 방지 하고 이중 검사 잠 금 체제 로 인 한 문 제 를 해결 할 수 있 습 니 다.
public class Singleton {
private volatile Singleton instance = null;
public Singleton getInstance(){
if(instance == null){
synchronized(this){
if(instance == null){
instance = new Singleton();
}
}
}
return instance;
}
// other function
}
싱글 톤 이 가 변 적 이지 않 은 대상 이 고 모든 속성 이 가 변 적 이지 않다 면 volatile 키 워드 를 수식 할 필요 가 없습니다.자바 언어 는 가 변 적 이지 않 은 대상 에 대한 인용 으로 그 행 위 는 int, float 와 같 기 때문에 읽 기와 쓰기 작업 은 모두 원자 적 이다.
그러나 가장 간단 하고 고상 한 방식 으로 인 스 턴 스 를 만 드 는 것 은 static 를 사용 하 는 것 입 니 다.
class Singleton {
private static Singleton instance = new Singleton();
}
자바 언어 에 따 르 면 필드 의 초기 화 는 인 용 된 후에 이 루어 지 며 모든 스 레 드 는 필드 에서 초기 화 된 후에 해당 하 는 작업 을 할 것 입 니 다.
Reference :
http://www.cs.umd.edu/~pugh/java/memoryModel/
http://gee.cs.oswego.edu/dl/cpj/jmm.html
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 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에 따라 라이센스가 부여됩니다.