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
'TIPS' 카테고리의 다른 글
ThreadLocal — 스레드별로 고립된 변수 저장소 만들기 (6) | 2025.06.09 |
---|---|
자바에서 volatile, synchronized, AtomicInteger 언제 써야 할까? (0) | 2025.05.26 |
자바에서 불변 객체(Immutable Object)의 중요성과 정의 (0) | 2025.05.19 |
Java에서 ==와 equals()의 차이 완벽 정리 (Heap vs Stack 메모리 차이 포함) (0) | 2025.05.12 |
멀티스레드 환경에서 발생할 수 있는 충돌 사례 및 해결 방법 (1) | 2025.05.06 |