-1

에 잠금 장치에 동기화 사용하는 잠금 퍼펙트 변환 (따라서 게으른) 그리고 그것은 한 번 이상 발생할 수 있습니다 (따라서 싱글 톤 패턴을 사용할 수 없습니다, 내가 틀렸다면 수정하십시오).는 JAVA 8에 <code>synchronized</code> 키워드를 사용하여 잠금 더블 체크를 구현하는 다음 코드를 고려 JAVA

어쨌든 먼저 synchronized 키워드를 사용하는 대신 JAVA 동시 패키지에서 Lock을 사용하려면 위의 코드를 어떻게 변환합니까?

그 후에 선택적으로 Lock 또는 synchronized 키워드를 사용하는 것에 대해 자유롭게 의견을 말하십시오.

이 질문은 잠금 대 동기화 비교가 아니라는 점을 기억하십시오. 코드 변환 부분에 응답하지 않은 응답 시도는 허용 된 대답으로 선택되지 않습니다.

import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 

public class HeavyInitializer { 
static final Logger logger = LoggerFactory.getLogger(HeavyInitializer.class); 
static HeavyInitializer singleton; 
public static synchronized HeavyInitializer getInstance() { 
    if (singleton==null) { 
     singleton = new HeavyInitializer(); 
    } 
    return singleton; 
} 
boolean initialized; 
private HeavyInitializer() { 
    initialized = false; 
} 

public synchronized void initialize() { 
    if (!initialized) { 
     heavyStuffDoneHere(); 
    } 
} 
public synchronized void reInitilize() { 
    if (needToReinitialise()) { 
     heavyStuffDoneHere(); 
    } 
} 

private void heavyStuffDoneHere() { 
    initialized = true; 
} 

private boolean needToReinitialise() { 
    if (!initialized) 
     return false; 
    boolean ret = false; 
    //Do your check here... and set ret  
    return ret; 
} 

} 

Oracle's doc에서 :

+0

가능한 복제 (http://stackoverflow.com/questions/4201713/synchronization-vs-lock) 구현 확장 –

+0

@ErwinBolwidt 예를 들어 비교에만 집중하고이 질문을 완전히 무시하면 주요 질문 인 동등한 코드 변환을 묻습니다. 당신이 원하지 않는 경우 비교에 대해 언급 할 필요는 없지만 코드 변환에 응답하십시오. – user1589188

+0

싱글 톤을 사용할 수 있습니다. 하나의 가능한 아키텍처는 초기화 및 redo 초기화에 동기화 된 메서드를 사용하여 Singleton HeavyInitializer 클래스를 만드는 것입니다. – Chocksmith

답변

1

ReentrantLock을 사용하여 동기화 된 블록을 동등한 블록으로 변환하는 것은 매우 간단합니다.

처음에는 잠근 개체와 동일하거나 유사한 범위와 수명으로 잠금을 만듭니다. 여기서 MyClass.class에 잠겨 있으므로 정적 잠금이되므로 MyClass.initLock과 같이 MyClass의 정적 잠금에 매핑 할 수 있습니다.

그런 다음 각각의 대체 :

synchronized (object) { 

모두 함께 퍼팅

lock.lock(); 
try { 

} finally { 
    lock.unlock(); 
} 

각 관련 닫는 중괄호와 함께 당신이 :

private final static ReentrantLock initLock = new ReentrantLock(); 

private static void redoHeavyInitialisation() { 
    if (needToReinitialise()) { 
     MyClass.initLock.lock(); 
     try { 
      if (needToReinitialise()) { 
       doHeavyInitialisation(); 
      } 
     } finally { 
      MyClass.initLock.unlock(); 
     } 
    } 
} 

성능 측면에서 접근 방법 사이에 약간의 주광이 있습니다. 본질적으로 동일한 의미를 가지며 일반적으로 유사한 기본 메커니즘을 사용합니다. 과거에는 성능상의 차이가 있었는데 때로 최적화가 그 중 하나 또는 다른 것에 영향을 주었기 때문에 일부 JVM에서는 차이점을 발견 할 수 있지만 전체 점 이중 확인 잠금은 어쨌든 잠금을 피하는 것이므로, 그래서 가장 단순한 것을하십시오. needToReinitialise() 메서드가 실행되는 동안 매우 짧은 일시적 기간 동안 만 잠금을 얻으므로 잠금 비용에는 지속적인 영향이 없습니다.

+0

고맙습니다. 거의 최고의 답변입니다. ReentrantLock이되어야하는 이유에 대해 언급 해주시길 바랍니다. 그러나 'Lock'의 다른 변종은 사용되지 않았습니까? – user1589188

+0

'ReentrantLock'은 자바 8에서 내가 아는'Lock' 인터페이스의 직접 구현 가능한 유일한 구현체입니다. 다른 구현체에 대해 이야기하고 있습니까? @ user1589188 – BeeOnRope

+0

죄송합니다. 잠금 패키지를 의미했습니다. 읽기/쓰기, 스탬프 찍기, 잠금 지원 등이 있습니다. – user1589188

0

다음 코드를 고려 후 동기화 이러한 방법을 ...

을 두 가지 효과가 있습니다

  • 첫째, 그것은이 불가능하다 인터리브 (interleave) 할 동일한 객체에 대한 동기화 된 메소드의 호출. 한 스레드가 객체에 대해 동기화 된 메소드를 실행할 때 첫 번째 스레드가 객체로 완료 될 때까지 동일한 객체 블록 (실행 중단)에 대해 동기화 된 메소드를 호출하는 다른 모든 스레드.

  • 둘째, 동기화 된 메서드가 종료 될 때 동일한 개체에 대한 동기화 된 메서드의 후속 호출과 자동적으로 발생 - 관계를 설정합니다. 이렇게하면 모든 스레드에서 객체 상태에 대한 변경 사항을 볼 수 있습니다.

잠금을 사용하려고하면 동기화 된 블록을 다시 구현하려고합니다. 필요 없습니다.

+0

. 나는 당신에게 점수를주고 싶지만 당신이 가지고있는 것은 나의 질문에 예와 같이'synchronized '를 사용한다. 나의 질문에 전혀 답하지 않는다. – user1589188

+1

그냥 대체 아키텍처를 제공하고 제시하려고합니다. 내 경험에 의하면 잠금 또는 세마포어와 동기화 된 구현을하면 실행 시간에 해결하기 어려운 버그가 발생합니다. 나는 동기화 된 싱글 톤 아키텍처를 사용할 것이다. – Chocksmith

-1

싱글 톤 잠금을 두 번 검사하고 단일 객체가 직렬화를 사용하여 중단되지 않도록합니다.

package pattern.core.java; import java.io.Serializable;

공용 클래스 싱글 톤 객체 직렬화 {

private static final long serialVersionUID = 1L; 
private static Singleton sg; 

private Singleton() { 
} 

public static Singleton getSingletonObj() { 
    if (sg == null) { 
     synchronized (sg) { 
      if (sg == null) { 
       sg = new Singleton(); 
      } 
     } 
    } 
    return sg; 
} 


/* 
* this method ensures that new object will not be created for singleton 
* class using serialization and deserialization 
*/ 
protected Object readResolve() { 
    return sg; 
} 

/* 
* @Override protected Object clone() throws CloneNotSupportedException { 
* throw new CloneNotSupportedException(); } 
*/ 

@Override 
protected Object clone() throws CloneNotSupportedException { 
    return sg; 
} 

} [잠금 대 동기화]의

+1

코드를 올바르게 포맷하십시오. – Ibo