2016-07-30 2 views
4

이것은 Joshua Bloch가 쓴 책에서 가져온 것입니다.스레드가 이미 보유하고있는 잠금을 획득하려고하면 어떻게됩니까?

저는 영어가 모국어가 아니므로 의심의 여지가없는 이유를 묻습니다. 쓰레드가 이미 보유하고 잠금을 획득 을 시도하는 경우 고유 잠금 재진입 때문에

요청 이 성공합니다. Reentrancy는 ** 당 호출 **보다는 스레드 당 에서 잠금이 획득됨을 의미합니다.

메소드 단위 호출을 의미합니까? 니핏을 고려

class Factoriser{ 

     public synchronized void doSomething(){ 
      // code goes here 
     } 
} 

이 스레드 A는 상기 인스턴스 메소드 해봐요를 갖는 오브젝트에 잠금을 획득 할 수있는 가정하자. 같은 thread thread A가 같은 오브젝트 인스턴스 메소드 doSomething()에 대해서 락을 취득하는 몇개인가의 이유에 의해 (이전의 락이 아직 릴리즈되어 있지 않은 것도 상상해보십시오).

Joshua의 설명을 올바르게 이해하면 2 개의 메소드 호출/호출이 있어도 하나의 잠금 만있을 것입니다. 제 이해가 100 % 정확합니까? 예증 해주십시오. 나는 저자가 아래 문단에서 이것을 분명하게하기 때문에 혼란 스럽다.

재진입은 각 잠금과 획득 카운트와 소유 스레드를 연관시킴으로써 구현됩니다. 카운트가 0이면 잠금이 해제 된 것으로 간주됩니다. 스레드가 이전에 잠금 해제 된 잠금을 획득하면 JVM은 소유자 을 기록하고 획득 수를 1로 설정합니다. 동일한 스레드 이 다시 잠금을 획득하면 소유 스레드가 동기화 된 블록을 종료 할 때 카운트가 증가하면 카운트가 감소됩니다. 카운트가 0에 도달하면 잠금이 해제됩니다.

Reentrancy/locks 획득이 호출 기준이 아닌 경우 위에서 설명한 시나리오에서 JVM에 의해 수행 된 카운트가 2로 설정된 이유는 무엇입니까?

+2

** ** 굵게 ** ** 많이 ** 있습니다. 사실 ** 너무 대담합니다 ** ** 무의미 해지고 ** ** 산만 해졌습니다 **. – Andreas

+0

개체 당 하나의 잠금 장치 만 있습니다. 임의의 수의 호출은 동일한 잠금을 요구합니다 (성공적으로). 마지막 잠금이 해제되면 개체가 더 이상 잠기지 않습니다. 이게 왜 어려운가요? – markspace

+0

@ Andreas : 고마워. 제거되었습니다. –

답변

2

카운터는 잠금 획득 및 배설물을 일치시키는 데 사용됩니다.

// calling obj.foo() 
synchronized(obj) { 
    // Do the foo-work 
} 

것은 이제 우리가 두 개의 동기화 방법을 가정 해 봅시다 : 잠금 카운터가 0이 synchronized 같은 방법 foo()을 표시하고 객체를 호출하는 경우에만 해제 할 수 obj 다음 블록과 동일 foo()bar() 및 후자는 전자에서 호출됩니다. 카운터없이

final FooBar obj = new FooBar(); 

// calling obj.foo() 
synchronized(obj) { // 1. here the lock is acquired, the counter is set to 1 

    // do some foo-work 

    // calling obj.bar() 
    synchronized(obj) { // 2. the same lock object, the counter is set to 2 
     // do the bar-work 
    } // 3. the counter is set to 1, the lock is still not released 

    // continue doing the foo-work 
} // 4. the counter is 0, the lock is released 

, 우리는 우리가 외부 동기화 블록에 여전히 있기 때문에 오류가 될 것이다 잠금을 해제 할 단계 3 : 호출은 다음과 같은 구조를 가지고 있습니다. 따라서 카운터는 재진입을 올바르게 구현하는 데 필요합니다.

+0

전체 개체가 잠겨 있습니까? 또는 해당 개체에 대해 동기화 된 것으로 표시된 메서드 만. –

+0

나는 당신의 질문을 완전히 이해하고 있는지 확신하지 못합니다. 모든 동기화 된 메소드는 동일한 잠금 객체, 즉이 메소드가 호출되는 바로 그 객체를 사용합니다 (정적 동기화 된 메소드는'Class' 객체를 사용합니다). 따라서 전체 객체가 잠겨 있다고 말할 수 있습니다. 그러나 synchronized로 표시되지 않은 메소드는 활성 잠금에 관계없이 계속 호출 할 수 있습니다. 각각의 동기화 된 메서드를 비동기 된 메서드로 생각하면됩니다. 그러나이 메서드가 호출 된 개체에서 동기화되는 블록에 배치됩니다. 내 대답에 나와 있듯이 많은 것들을 이해하기 쉽습니다. –

+0

그리고 메서드 자체가 잠기지 않는 것이 중요합니다. 이미 특정 스레드에서 호출되어 여전히 작동하고있는 특정 객체 (또는 정적 인 경우 클래스)에 대해서만 '잠김'될 수 있습니다. 동시에 다른 스레드는 다른 개체에서 동일한 메서드를 호출 할 수 있으며 잠금을 위해 다른 개체를 사용하기 때문에 차단되지 않습니다. 그래서, 그것은 잠긴 것이지 방법이 아닙니다. 그러나 이러한 잠금은 동기화 된 메서드와 동일한 개체를 사용하는 동기화 된 블록에만 영향을줍니다. –

관련 문제