본문 바로가기

TIPS

ReentrantLock vs synchronized — 자바 락의 실전 비교

728x90
반응형
SMALL

 

 

 

멀티스레드 환경에서 공유 자원을 안전하게 다루기 위해 락(Lock)을 사용하는 건 기본 중의 기본이다.

그중 synchronized는 가장 널리 쓰이는 키워드지만, 실무에서는 ReentrantLock을 선택하는 경우도 많다.

둘의 차이는 단순히 문법적인 것만이 아니라, 유연성과 제어력의 차이에 있다.

 


1. synchronized — 자바의 전통적인 락

 

public synchronized void doSomething() {
    // 임계영역
}
 
  • 메서드나 블록에 synchronized를 붙이면 해당 영역에 한 번에 하나의 스레드만 접근 가능하다.
  • 락을 얻지 못한 스레드는 자동으로 블로킹(대기) 된다.
  • 락은 메서드가 끝나거나 블록이 종료될 때 자동으로 해제된다.

 

장점

  • 문법이 단순하고 자동으로 락 해제돼 실수할 가능성이 낮다.

 

단점

  • 락 획득 실패나 타임아웃 제어가 불가능하다.
  • 복잡한 상황에선 유연하게 제어하기 어렵다.

 


2. ReentrantLock — 더 유연한 락 제어

Lock lock = new ReentrantLock();

lock.lock(); // 락 획득
try {
    // 임계영역
} finally {
    lock.unlock(); // 꼭 해제!
}
 

 

핵심 특징

명시적 락 해제 필요

→ finally 블록에서 반드시 unlock() 호출 필요. 실수하면 데드락 발생 가능성 있음.

tryLock() 지원

→ 일정 시간만 기다리고 실패할 수 있음. 데드락 회피 전략으로 유용함.

 

if (lock.tryLock(2, TimeUnit.SECONDS)) {
    try {
        // 락 획득 성공 시 작업 수행
    } finally {
        lock.unlock();
    }
} else {
    // 락 획득 실패 시 대체 로직 수행
}
 

공정성(Fairness) 설정 가능

→ ReentrantLock(true)로 생성하면, 대기 중인 스레드에게 순서대로 락을 부여함.

→ 시스템에 따라 성능 저하가 있을 수 있음.


3. 비교 요약

 

항목
synchronized
ReentrantLock
사용 방법
키워드 기반
객체 기반
락 해제
자동
수동 (직접 unlock 필요)
락 획득 시도
불가능
tryLock()으로 가능
공정성 설정
불가능
가능 (new ReentrantLock(true))
조건 변수
불가능
가능 (Condition 객체 사용)

 


 

4. 실무에서 어떤 걸 써야 할까?

 

상황
추천
간단한 동기화
synchronized
데드락 회피, 락 획득 시도
ReentrantLock
조건 동기화(wait/notify 대신)
ReentrantLock + Condition
락 획득 순서를 엄격히 관리해야 할 때
ReentrantLock(true)

 

 


✅ 정리

  • synchronized는 단순하지만 제어가 부족하다.
  • ReentrantLock은 제어가 유연하지만 사용법이 복잡하다.
  • 무조건 하나가 더 낫다고 보긴 어렵고, 상황에 따라 선택해야 한다.

 

 

 

 

728x90
반응형
LIST