Search
Duplicate

ReentrantLock

synchronized와 같이 동기화를 제공하지만, 동기화의 시작과 끝을 지정할 수 있는 객체

개요

기존의 synchronized는 메서드 혹은 블록내에 작성을 할 수 있으며 잠금과 반환이 자동으로 이뤄진다.
public synchronized void order(){ ... } //메서드가 선언된 객체에 대한 잠금및 반환이 자동이다. public void order(){ synchronized(products) { ... } //자원에 대한 잠금과 반환이 자동으로 이뤄진다. }
Java
복사
하지만, 상황에따라 이런 잠금의 시작과 잠금의 종료를 내가 임의로 정해야 하는 경우가 생기고 이런 경우 사용하게 되는 상호베타적 락이 이 Reentrant Lock으로 JDK1.5에서 추가되었으며 java.util.concurrent.locks 패키지에서 제공되고 있다.

사용법

사용법은 간단하다. lock , unlock 메서드를 통해 잠금(Lock)의 시작과 종료를 명시적으로 작성해줄 수 있다.
class X { private final ReentrantLock lock = new ReentrantLock(); // ... public void m() { lock.lock(); // block until condition holds try { // ... method body } finally { lock.unlock() } } }
Java
복사
⇒ ReentrantLock 참조변수는 왠만해서는 private final로 선언해주자.
⇒ unlock()은 작업이 끝나고 무조건 실행되어 잠금을 풀어줘야 하기때문에 finally 블록에 작성하여 try 블록 내에서 오류가 생기더라도 unlock()은 실행될 수 있도록 한다.
기존 쓰레드에는 특정 쓰레드에서 객체의 락을 너무 오랫동안 가지지 않도록 하기 위해서 만든 메서드들이 있는데,
이를 이용해 스레드가 로직 진행을 더 이상 하지 못하고 대기해야하는 상황일 때 wait()을 호출해 락을 반납 후 기다리도록 할 수 있다. 그 밖에 notify()를 이용해 작업을 진행할 수 있는 상황에서 다시 락을 얻어 진행(재진입)할수도 있다. ReentLock에서는 이런 메서드들을 그대로 사용할 수는 없고 다음과 같은 메서드를 제공한다.
await() : wait() 메서드와 동일
signal(): notify() 메서드와 동일
signalAll(): notifyAll()메서드와 동일
각각의 메서드들은 기존에 존재하던 메서드와 동일하게 동작을 한다.
다만, 사용시에 바로 사용을 할 수 있는 것은 아니고 newCondition()이라는 메서드를 호출해서 반환받은 Condition 타입의 객체를 통해서 사용할 수 있다.
class X { private final ReentrantLock lock = new ReentrantLock(); private final Condition condition = lock.newCondition(); // ... public void m() { lock.lock(); // block until condition holds try { // ... method body condition.await(); condition.signal(); condition.signalAll(); } finally { lock.unlock() } } }
Java
복사

참고

다음 링크는 ReentrantLock 클래스의 공식 API 문서다. 필요하다면 참고하여 사용법을 학습하도록 하자.

관련글