이 글은 원 저자 Jakob Jenkov의 허가로 포스팅된 번역물이다.

원문 URL : http://tutorials.jenkov.com/java-concurrency/reentrance-lockout.html



재진입 락아웃은 데드락중첩 모니터 락아웃과 유사한 현상이다. 자바의 락읽기/쓰기 락에서 다뤄지기도 했다.


재진입 락아웃은 한 쓰레드가 재진입이 불가능한 Lock 이나 ReadWriteLock, 이외 다른 동기화에 재진입 요청을 시도할 때 발생한다. 재진입이란 이미 락을 획득한 쓰레드가 자신이 보유한 락과 동일한 락을 다시 요청하는 동작을 의미한다. 자바의 synchronized 블록은 재진입 락이다. 때문에 아래의 코드는 문제 없이 수행된다.


public class Reentrant{

  public synchronized outer(){
    inner();
  }

  public synchronized inner(){
    //do something
  }
}


outer() 와 inner() 는 synchronized 로 선언되었다. 자바에서 메소드 선언부의 synchronized 는 synchronized(this) 블록과 동일한 의미를 가지므로, outer() 와 inner() 메소드는 같은 모니터 객체('this') 에 대한 동기화를 수행한다. 한 쓰레드가 모니터 객체의 락을 획득하면, 같은 모니터 객체에 대해 선언된 모든 synchronized 블록으로의 진입권을 갖는다. 이것이 재진입이다. 쓰레드는 자신이 소유한 락에 대한 모든 synchronized 블록으로 진입할 수 있다.


다음 Lock 구현은 비 재진입 락이다.


public class Lock{

  private boolean isLocked = false;

  public synchronized void lock()
  throws InterruptedException{
    while(isLocked){
      wait();
    }
    isLocked = true;
  }

  public synchronized void unlock(){
    isLocked = false;
    notify();
  }
}


한 쓰레드가 unlock() 호출 없이 lock() 을 두 번 호출하면, 두 번째 lock() 호출에 의해 쓰레드는 블록된다. 재진입 락아웃이 발생하는 것이다.


재진입 락아웃을 방지하는 방법은 두 가지가 있다.


  1. 재진입을 시도하지 않는다.
  2. 재진입 락을 사용한다.

두 방법 중 어느 쪽이 알맞느냐는 구체적인 상황에 달려있다. 재진입 락 종종 비 재진입 락만큼 제대로 동작하기 않기도 하고, 구현하기도 더 어렵지만, 꼭 필요한 것이 아닐 수도 있다. 재진입 락이 필요할지 필요하지 않을지는 구체적인 상황에 따라 결정되어야 한다.





'Java > Concurrency' 카테고리의 다른 글

블로킹 큐(Blocking Queues)  (3) 2017.05.22
세마포어(Semophores)  (0) 2017.05.22
읽기/쓰기 락(Read/Write Locks in Java)  (0) 2017.05.16
자바의 락(Locks in Java)  (0) 2017.05.09
슬립 상태(Slipped Conditions)  (0) 2017.04.23

+ Recent posts