원문 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() 호출에 의해 쓰레드는 블록된다. 재진입 락아웃이 발생하는 것이다.
재진입 락아웃을 방지하는 방법은 두 가지가 있다.
- 재진입을 시도하지 않는다.
- 재진입 락을 사용한다.
'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 |