4주차 Unit 4.4 — 모니터 락(Monitor Lock)의 동작

Psj·2026년 5월 21일

F-lab

목록 보기
135/239

Unit 4.4 — 모니터 락(Monitor Lock)의 동작

F-LAB JAVA · 4주차 · Phase 4 · 동기화: synchronized와 메모리 가시성
★ 마스터 Unit — 면접 단골 (★★★)


📌 학습 목표

이 Unit을 끝내면 다음을 답할 수 있어야 한다.

  • 모니터 락 (Monitor Lock / Intrinsic Lock) 의 정의는?
  • 모든 자바 객체가 모니터 락 을 가지는 의미는?
  • synchronized 진입 시 락 획득 과정 (성공/실패) 은?
  • BLOCKED 상태로 대기 하는 메커니즘은?
  • 메서드/블록 종료 시 락 자동 반환 은?
  • 락 경쟁 시나리오 (100 스레드, 1개 성공) 는?
  • 락 획득 순서 (공정성, Fairness) 가 보장되는가?
  • synchronized 의 단점 3가지 는?
  • 모니터의 객체 헤더 (Mark Word) 는?

🎯 핵심 한 문장

모니터 락 (Monitor Lock, = intrinsic lock / 고유 락) 은 모든 자바 객체가 내부적으로 하나씩 가지는 락으로, synchronized 가 이 락을 사용하여 상호 배제를 구현한다.
스레드가 synchronized 에 진입하려면 그 객체의 모니터 락 획득을 시도하며, 성공하면 RUNNABLE 로 진입, 실패하면 (다른 스레드가 보유 중) BLOCKED 상태로 대기 한다.
synchronized 메서드/블록이 종료되면 (정상 또는 예외) 락이 자동으로 반환 되고, 대기 중이던 BLOCKED 스레드 중 하나가 락을 획득한다.
100개 스레드가 같은 synchronized 블록 진입을 시도하면 1개만 성공하고 99개는 BLOCKED 되며, 락 획득 순서는 자바 표준에 정의되어 있지 않다 (공정성 X) — 먼저 대기한 스레드가 먼저 받는다는 보장이 없다.
synchronized 의 단점은 (1) 무한 대기 (타임아웃 불가), (2) 인터럽트 불가 (대기 중 깰 수 없음), (3) 공정성 보장 X 이며, 이를 극복하는 도구가 Phase 5 의 ReentrantLock 이다.

비유 — 회의실 1개 열쇠와 대기자들

모니터 락 = 회의실 열쇠 (객체마다 1개):

진입 시도:
  - 열쇠 있으면 → 들어감 (RUNNABLE)
  - 열쇠 없으면 → 문 앞 대기 (BLOCKED)

종료 시:
  - 열쇠 반납
  - 대기자 중 1명이 가져감

100명 대기 (락 경쟁):
  - 열쇠 1개
  - 1명만 들어감
  - 99명 문 앞 대기 (BLOCKED)

공정성 X (먼저 온 순서 보장 X):
  - 열쇠 반납 시
  - 누가 가져갈지 OS 가 결정
  - 먼저 기다린 사람이 못 받을 수도
  - "새치기" 가능 (barging)

단점:
  - 무한 대기 (포기 불가)
  - 누가 두드려도 (인터럽트) 안 나옴
  - 줄 순서 (공정성) 없음

→ 모니터 락 = 객체별 열쇠, 100명 중 1명, 공정성 없음.


🧭 9개 섹션 로드맵

1. 모니터 락의 정의
2. 모든 객체가 모니터 락
3. 락 획득 과정 (성공/실패)
4. BLOCKED 대기 메커니즘
5. 락 자동 반환
6. 락 경쟁 시나리오 (100 스레드)
7. 공정성 (Fairness)
8. synchronized의 단점 3가지
9. 면접 + 자기 점검 + 마스터 50문항

1️⃣ 모니터 락의 정의

1.1 모니터 락이란

모니터 락 (Monitor Lock):

  = Intrinsic Lock (고유 락)
  = Object Lock

  모든 자바 객체가 내부적으로 가지는 락.
  synchronized 가 이 락을 사용.

특징:
  - 객체당 1개
  - 상호 배제
  - 재진입 가능

1.2 모니터의 개념

모니터 (Monitor):

  동기화 메커니즘.
  - 락 (Lock) — 상호 배제
  - 대기 집합 (Wait Set) — wait/notify

자바:
  - 모든 객체가 모니터
  - synchronized = 락 사용
  - wait/notify = 대기 집합 (Phase 6)

1.3 intrinsic 의 의미

"intrinsic" (고유):

  - 객체에 내재된 락
  - 별도 객체 생성 불필요
  - 모든 객체에 기본 내장

대조:
  - ReentrantLock (명시적 락)
  - 별도 객체 생성 (new ReentrantLock)

1.4 모니터 락 사용

Object obj = new Object();

// obj 의 모니터 락 사용
synchronized (obj) {
    // obj 의 락 보유
}

// 모든 객체 가능
synchronized (this) { }          // this 의 락
synchronized (myList) { }        // myList 의 락
synchronized (String.class) { }  // Class 객체 락

1.5 모니터 락의 구성

모니터 락 구성:

1. 소유 스레드 (Owner)
   - 현재 락 보유 스레드

2. 재진입 카운트 (Recursion Count)
   - 같은 스레드 재획득 횟수

3. 진입 대기 집합 (Entry Set)
   - 락 대기 스레드 (BLOCKED)

4. 대기 집합 (Wait Set)
   - wait() 한 스레드 (WAITING)

1.6 ILIC 의 맥락

public class MonitorLockBasics {
    
    private int count = 0;
    private final Object lock = new Object();   // lock 의 모니터
    
    public void increment() {
        synchronized (lock) {   // lock 의 모니터 락 사용
            count++;
        }
    }
    
    // this 의 모니터
    public synchronized void incrementThis() {
        count++;   // this 의 락
    }
    
    // 모든 객체가 모니터 락 보유
    // - lock (Object)
    // - this (ShipmentService)
    // - String, List, 등 모두
}

1.7 자기 점검 답변

모니터 락의 정의는?

:
1. 정의:

  • 모든 객체의 내장 락
  • intrinsic lock
  • synchronized 가 사용
  1. 모니터:

    • 락 + 대기 집합
    • 동기화 메커니즘
  2. intrinsic:

    • 내재된 락
    • 별도 생성 X
  3. 구성:

    • 소유 스레드
    • 재진입 카운트
    • 진입/대기 집합

2️⃣ 모든 객체가 모니터 락

2.1 모든 객체

모든 자바 객체가 모니터 락:

  - Object 부터 상속
  - 객체 헤더에 락 정보
  - 별도 설정 불필요

따라서:
  - 어떤 객체든 synchronized 가능
  - new Object(), this, List, 등

2.2 객체 헤더 (Object Header)

객체 헤더 구조:

  ┌──────────────────────┐
  │ Mark Word            │  ← 락 정보, 해시, GC age
  ├──────────────────────┤
  │ Klass Pointer        │  ← 클래스 메타데이터
  ├──────────────────────┤
  │ (배열이면 길이)        │
  └──────────────────────┘
  ┌──────────────────────┐
  │ 인스턴스 데이터        │  ← 필드
  └──────────────────────┘

2.3 Mark Word

Mark Word (락 정보):

  객체 헤더의 일부.
  락 상태에 따라 내용 변함:

  - Unlocked: 해시코드, GC age
  - Biased: 편향 스레드 ID
  - Lightweight: 락 레코드 포인터
  - Heavyweight: 모니터 포인터
  - GC: 마킹

  → 락 상태를 Mark Word 로 표현

2.4 락 상태 전이

락 상태 전이 (Java 6+ 최적화):

No Lock
  ↓ (단일 스레드 접근)
Biased Lock (편향 락)
  ↓ (다른 스레드 경합)
Lightweight Lock (경량 락, CAS)
  ↓ (경합 심화)
Heavyweight Lock (중량 락, 모니터)

  - 경합 적으면 가벼움 (빠름)
  - 경합 심하면 무거움 (OS 모니터)

2.5 락의 비용

락 상태별 비용:

Biased Lock:
  - 거의 무비용
  - 단일 스레드 반복

Lightweight Lock:
  - CAS 연산
  - 경합 적을 때

Heavyweight Lock:
  - OS 모니터
  - 컨텍스트 스위칭
  - 비쌈

→ JVM 이 자동 최적화

2.6 ILIC 의 맥락

public class ObjectMonitorExample {
    
    // 모든 객체가 모니터 락
    private final Object lock1 = new Object();
    private final List<Shipment> list = new ArrayList<>();
    private final Map<Long, Shipment> map = new HashMap<>();
    
    public void useVariousLocks() {
        synchronized (lock1) {   // Object 의 모니터
            // ...
        }
        
        synchronized (list) {   // ArrayList 의 모니터
            list.add(shipment);
        }
        
        synchronized (map) {   // HashMap 의 모니터
            map.put(1L, shipment);
        }
        
        // 모두 각자의 모니터 락
        // 독립적
    }
}

2.7 자기 점검 답변

모든 객체가 모니터 락을 가지는 의미는?

:
1. 모든 객체:

  • Object 부터 상속
  • 객체 헤더에 락 정보
  1. 객체 헤더:

    • Mark Word (락 정보)
    • Klass Pointer
  2. Mark Word:

    • 락 상태 표현
    • 상태별 내용 변함
  3. 락 상태 전이:

    • Biased → Lightweight → Heavyweight
    • JVM 자동 최적화

3️⃣ 락 획득 과정 (성공/실패)

3.1 락 획득 시도

synchronized 진입 시:

  1. 락 획득 시도 (monitorenter)
  2. 성공:
     - 락 보유
     - RUNNABLE (진입)
  3. 실패 (다른 스레드 보유):
     - BLOCKED (대기)

3.2 성공 시나리오

락 획득 성공:

스레드 A:
  synchronized (lock) 진입
    ↓ monitorenter
  락 비어있음 → 획득
    ↓
  RUNNABLE (임계 영역 실행)
    ↓ monitorexit
  락 반납

3.3 실패 시나리오

락 획득 실패:

스레드 B (A 가 락 보유 중):
  synchronized (lock) 진입
    ↓ monitorenter
  락 있음 (A 보유) → 획득 실패
    ↓
  BLOCKED (진입 대기 집합)
    ↓ (A 가 반납)
  락 획득 → RUNNABLE

3.4 monitorenter/monitorexit

바이트코드:

synchronized (lock) {
    // ...
}

→
  monitorenter   // 락 획득
  // 임계 영역
  monitorexit    // 락 반납 (정상)
  monitorexit    // 락 반납 (예외 시)

3.5 시각화

락 획득 (A 성공, B 실패):

lock 모니터:
  Owner: A (보유)
  Entry Set: [B]  (대기)

스레드 A: [monitorenter 성공][임계 영역][monitorexit]
스레드 B: [monitorenter 실패 → BLOCKED────][획득][실행]
                                          ↑ A 반납 후

3.6 ILIC 의 맥락

@Service
public class LockAcquisition {
    
    private int counter = 0;
    private final Object lock = new Object();
    
    public void process() {
        // monitorenter (락 획득 시도)
        synchronized (lock) {
            // 성공: RUNNABLE (여기 실행)
            // 실패: BLOCKED (다른 스레드 대기)
            counter++;
            doWork();
        }
        // monitorexit (락 반납)
    }
    
    private void doWork() {
        // 임계 영역
        // 이 동안 다른 스레드 BLOCKED
    }
}

3.7 자기 점검 답변

락 획득 과정 (성공/실패)은?

:
1. 시도:

  • monitorenter
  • 락 획득 시도
  1. 성공:

    • 락 보유
    • RUNNABLE
  2. 실패:

    • 다른 스레드 보유
    • BLOCKED
  3. 바이트코드:

    • monitorenter (획득)
    • monitorexit (반납)

4️⃣ BLOCKED 대기 메커니즘

4.1 BLOCKED 상태

BLOCKED 상태:

  모니터 락을 획득하지 못해
  진입 대기 집합 (Entry Set) 에서 대기.

특징:
  - CPU 사용 X (대기)
  - 락 반납 시 깨어남
  - 인터럽트로 못 깨움

4.2 진입 대기 집합

Entry Set (진입 대기 집합):

  락을 기다리는 스레드들.
  - BLOCKED 상태
  - 락 반납 시 경쟁

vs Wait Set (대기 집합):
  - wait() 한 스레드
  - WAITING 상태
  - notify 로 깨어남 (Phase 6)

4.3 시각화

모니터 구조:

      모니터 (lock)
  ┌─────────────────────┐
  │ Owner: 스레드 A      │  ← 현재 보유
  ├─────────────────────┤
  │ Entry Set:          │  ← 락 대기 (BLOCKED)
  │   [B, C, D]         │
  ├─────────────────────┤
  │ Wait Set:           │  ← wait() (WAITING)
  │   [E, F]            │
  └─────────────────────┘

  A 반납 시 → Entry Set 에서 하나 선택

4.4 BLOCKED 의 깨어남

BLOCKED → RUNNABLE:

  락 보유 스레드가 반납 (monitorexit)
    ↓
  Entry Set 에서 하나 선택
    ↓
  선택된 스레드 락 획득
    ↓
  RUNNABLE

  - 선택은 OS/JVM (공정성 X)
  - 인터럽트로 안 깨어남

4.5 BLOCKED vs WAITING

BLOCKED vs WAITING:

BLOCKED:
  - 락 대기 (Entry Set)
  - synchronized 진입 실패
  - 락 반납 시 깨어남

WAITING:
  - wait() (Wait Set)
  - 명시적 대기
  - notify 시 깨어남

핵심:
  - BLOCKED: 락 경쟁
  - WAITING: 조건 대기

4.6 ILIC 의 맥락

@Service
public class BlockedMechanism {
    
    private final Object lock = new Object();
    
    public void longOperation() {
        synchronized (lock) {
            // 오래 점유
            try { Thread.sleep(5000); } catch (Exception e) {}
            // 이 동안 다른 스레드 BLOCKED
        }
    }
    
    // 모니터링 — BLOCKED 확인
    public void monitorBlocked(List<Thread> threads) {
        long blockedCount = threads.stream()
            .filter(t -> t.getState() == Thread.State.BLOCKED)
            .count();
        
        if (blockedCount > 0) {
            log.warn("{} threads blocked on lock", blockedCount);
            // jstack 으로 어떤 락인지 확인
        }
    }
}

4.7 자기 점검 답변

BLOCKED 대기 메커니즘은?

:
1. BLOCKED:

  • 락 못 얻어 대기
  • Entry Set
  • CPU X
  1. Entry Set:

    • 락 대기 (BLOCKED)
    • vs Wait Set (WAITING)
  2. 깨어남:

    • 락 반납 시
    • 하나 선택 (공정성 X)
    • 인터럽트 X
  3. vs WAITING:

    • 락 경쟁 vs 조건 대기

5️⃣ 락 자동 반환

5.1 자동 반환

락 자동 반환:

  synchronized 블록/메서드 종료 시
  락 자동 반환.

종료:
  - 정상 종료 (return)
  - 예외 발생 (throw)
  - 둘 다 반환 보장

5.2 정상 종료

synchronized (lock) {
    count++;
    // 블록 끝
}
// monitorexit (자동 반환)

5.3 예외 시 반환

synchronized (lock) {
    count++;
    throw new RuntimeException();   // 예외!
    // 그래도 monitorexit (반환 보장)
}
// 예외 전파되지만 락은 반환

// 바이트코드:
// monitorenter
// try {
//   // 임계 영역
// } finally {
//   monitorexit   // 예외 시에도
// }

5.4 자동 반환의 장점

자동 반환의 장점:

  - 명시적 unlock 불필요
  - 예외 시에도 안전
  - 데드락 방지 (락 잔류 X)

대조 (ReentrantLock):
  - 명시적 unlock 필요
  - try-finally 필수
  - 깜박하면 데드락

5.5 시각화

자동 반환:

정상:
  monitorenter → [임계 영역] → monitorexit
                                  ↑ 자동

예외:
  monitorenter → [임계 영역 중 예외] → monitorexit
                                         ↑ 자동 (예외 시에도)

  → 락 항상 반환 (안전)

5.6 ILIC 의 맥락

@Service
public class AutoRelease {
    
    private int counter = 0;
    private final Object lock = new Object();
    
    // 자동 반환 (예외 시에도)
    public void process(Shipment shipment) {
        synchronized (lock) {
            counter++;
            validate(shipment);   // 예외 가능
            // 예외 발생해도 락 자동 반환
        }
        // 데드락 위험 없음
    }
    
    private void validate(Shipment s) {
        if (s == null) {
            throw new IllegalArgumentException();
            // 예외! 하지만 락은 반환됨
        }
    }
    
    // synchronized 장점:
    // - unlock 깜박할 일 없음
    // - 예외 시에도 안전
    // (ReentrantLock 은 try-finally 필수 — Phase 5)
}

5.7 자기 점검 답변

락 자동 반환은?

:
1. 자동 반환:

  • 블록/메서드 종료 시
  • 정상/예외 모두
  1. 예외 시:

    • monitorexit 보장
    • finally 처럼
  2. 장점:

    • unlock 불필요
    • 예외 안전
    • 데드락 방지
  3. vs Lock:

    • synchronized: 자동
    • ReentrantLock: 명시적 (try-finally)

6️⃣ 락 경쟁 시나리오 (100 스레드)

6.1 시나리오

100 스레드 락 경쟁:

  100개 스레드가 같은 synchronized 블록 진입 시도.

결과:
  - 1개만 성공 (락 획득)
  - 99개 BLOCKED (대기)

→ 직렬화 (하나씩 처리)

6.2 코드

public class HundredThreadsContention {
    private int counter = 0;
    private final Object lock = new Object();
    
    public void demo() throws InterruptedException {
        List<Thread> threads = new ArrayList<>();
        
        for (int i = 0; i < 100; i++) {
            Thread t = new Thread(() -> {
                synchronized (lock) {   // 100개 경쟁
                    counter++;
                    sleep(10);   // 점유
                }
            });
            t.start();
            threads.add(t);
        }
        
        for (Thread t : threads) t.join();
        
        System.out.println("Counter: " + counter);   // 정확히 100
        // 하지만 100 × 10ms = 약 1초 (직렬화)
    }
}

6.3 직렬화

100 스레드 직렬화:

  락 1개 → 한 번에 1개만 진입.

  스레드 1: [락][10ms]
  스레드 2:      [BLOCKED][락][10ms]
  스레드 3:               [BLOCKED][락][10ms]
  ...

  전체 시간 = 100 × 10ms = 1초
  (병렬성 없음, 직렬)

6.4 경합의 영향

경합 (Contention) 의 영향:

높은 경합:
  - 많은 BLOCKED
  - 직렬화
  - 처리량 ↓
  - 컨텍스트 스위칭 ↑

낮은 경합:
  - 적은 대기
  - 빠른 처리

→ 경합 줄이기:
  - 락 분리
  - 범위 최소화
  - lock-free (Atomic)

6.5 시각화

락 경쟁:

      lock 모니터
   Owner: 스레드 1
   Entry Set: [2,3,4,...,100]  ← 99개 BLOCKED

스레드 1: [실행]
스레드 1 종료 → 반납
   → Entry Set 에서 1개 선택 (예: 스레드 50)
   → 스레드 50 실행
   ...

  순차적 (직렬화)

6.6 ILIC 의 맥락

@Service
public class ContentionExample {
    
    private int processedCount = 0;
    private final Object lock = new Object();
    
    // ❌ 높은 경합 (모든 요청이 같은 락)
    public void processWithContention(Shipment shipment) {
        synchronized (lock) {
            processedCount++;
            doProcess(shipment);   // 시간 걸림
            // 모든 스레드 직렬화
        }
    }
    
    // ✓ 경합 줄이기 — Atomic
    private final AtomicInteger atomicCount = new AtomicInteger();
    
    public void processLowContention(Shipment shipment) {
        doProcess(shipment);   // 병렬
        atomicCount.incrementAndGet();   // lock-free
    }
    
    // ✓ 경합 줄이기 — 락 분리
    private final Object[] locks = new Object[16];
    {
        for (int i = 0; i < 16; i++) locks[i] = new Object();
    }
    
    public void processStriped(Shipment shipment) {
        int stripe = (int)(shipment.getId() % 16);
        synchronized (locks[stripe]) {   // 분산
            doProcess(shipment);
        }
        // 다른 stripe → 동시 가능
    }
    
    private void doProcess(Shipment s) { }
}

6.7 자기 점검 답변

락 경쟁 시나리오 (100 스레드)는?

:
1. 결과:

  • 1개 성공
  • 99개 BLOCKED
  1. 직렬화:

    • 하나씩 처리
    • 병렬성 X
  2. 경합 영향:

    • 처리량 ↓
    • 스위칭 ↑
  3. 줄이기:

    • 락 분리
    • Atomic (lock-free)
    • 범위 최소화

7️⃣ 공정성 (Fairness)

7.1 공정성이란

공정성 (Fairness):

  락 획득 순서가
  대기 순서와 일치하는가.

공정 (Fair):
  - 먼저 대기 → 먼저 획득 (FIFO)

비공정 (Non-fair):
  - 순서 보장 X
  - 새치기 가능 (barging)

7.2 synchronized 는 비공정

synchronized 의 공정성:

  공정성 보장 X (Non-fair).

  - 락 획득 순서 미정의
  - 먼저 대기한 스레드가
    먼저 받는다는 보장 없음
  - OS/JVM 이 결정

7.3 비공정의 문제

비공정의 문제:

1. 기아 (Starvation)
   - 특정 스레드가 계속 못 받음
   - 무한 대기 가능

2. 예측 불가
   - 어느 스레드가 받을지 모름

3. 순서 보장 안 됨
   - 처리 순서 중요하면 문제

장점:
  - 성능 (공정성 비용 없음)
  - 처리량 ↑

7.4 기아 시나리오

기아 (Starvation):

  스레드 A, B, C 가 락 경쟁:
  - A 가 자주 받음
  - C 가 계속 못 받음
  - C 기아 상태

비공정 락:
  - 운 나쁘면 특정 스레드 기아
  - 무한 대기 가능

7.5 공정성이 필요하면

// synchronized 는 비공정
synchronized (lock) { }   // 공정성 X

// 공정성 필요하면 ReentrantLock (Phase 5)
ReentrantLock fairLock = new ReentrantLock(true);   // 공정 모드
fairLock.lock();
try {
    // FIFO 순서
} finally {
    fairLock.unlock();
}

// 단, 공정 모드는 성능 ↓ (순서 관리 비용)

7.6 ILIC 의 맥락

@Service
public class FairnessExample {
    
    private final Object lock = new Object();
    
    // synchronized — 비공정 (순서 보장 X)
    public void processNonFair(Shipment shipment) {
        synchronized (lock) {
            // 먼저 대기한 스레드가 먼저 받는다는 보장 X
            doProcess(shipment);
        }
    }
    
    // 공정성 필요 시 — ReentrantLock(true) (Phase 5)
    private final ReentrantLock fairLock = new ReentrantLock(true);
    
    public void processFair(Shipment shipment) {
        fairLock.lock();   // FIFO 순서
        try {
            doProcess(shipment);
        } finally {
            fairLock.unlock();
        }
        // 순서 보장 (단 성능 ↓)
    }
    
    private void doProcess(Shipment s) { }
}

7.7 자기 점검 답변

공정성 (Fairness)이 보장되는가?

:
1. synchronized:

  • 비공정 (Non-fair)
  • 순서 보장 X
  1. 공정 vs 비공정:

    • 공정: FIFO
    • 비공정: 새치기 가능
  2. 문제:

    • 기아 (starvation)
    • 예측 불가
  3. 해결:

    • ReentrantLock(true)
    • 단 성능 ↓

8️⃣ synchronized의 단점 3가지

8.1 세 가지 단점

synchronized 의 단점 3가지:

1. 무한 대기
   - 타임아웃 설정 불가
   - 락 받을 때까지 무한

2. 인터럽트 불가
   - 대기 중 외부에서 못 깨움
   - interrupt() 안 통함

3. 공정성 보장 X
   - 순서 미정의
   - 기아 가능

8.2 단점 1 — 무한 대기

무한 대기:

  synchronized 진입 시 락 없으면
  무한정 대기 (BLOCKED).

  - 타임아웃 X
  - "1초만 기다리고 포기" 불가
  - 락 영원히 안 풀리면 영원히 대기

문제:
  - 데드락 시 회복 불가
  - 응답 지연

8.3 단점 2 — 인터럽트 불가

// synchronized 대기 중 인터럽트 안 통함
Thread t = new Thread(() -> {
    synchronized (lock) {   // 락 대기 (BLOCKED)
        // ...
    }
});
t.start();

t.interrupt();   // ❌ BLOCKED 는 인터럽트 안 됨
// 락 받을 때까지 계속 대기

// ReentrantLock 은 lockInterruptibly() 가능 (Phase 5)

8.4 단점 3 — 공정성 X

공정성 X (앞 섹션):

  - 순서 보장 안 됨
  - 기아 가능
  - 예측 불가

ReentrantLock(true) 로 해결 가능

8.5 ReentrantLock 의 극복 (Phase 5 예고)

// synchronized 한계
synchronized (lock) {
    // 무한 대기, 인터럽트 X, 비공정
}

// ReentrantLock 극복 (Phase 5)
ReentrantLock lock = new ReentrantLock(true);   // 공정

// 1. 타임아웃
if (lock.tryLock(5, TimeUnit.SECONDS)) {   // 5초만
    try { } finally { lock.unlock(); }
}

// 2. 인터럽트 가능
lock.lockInterruptibly();   // 인터럽트로 깰 수 있음

// 3. 공정성
new ReentrantLock(true);   // FIFO

8.6 ILIC 의 맥락

@Service
public class SynchronizedLimitations {
    
    private final Object lock = new Object();
    
    // ❌ synchronized 한계
    public void processSync(Shipment shipment) {
        synchronized (lock) {
            // 1. 무한 대기 (타임아웃 X)
            // 2. 인터럽트 X
            // 3. 비공정
            doProcess(shipment);
        }
    }
    
    // ✓ ReentrantLock 극복 (Phase 5)
    private final ReentrantLock reentrantLock = new ReentrantLock();
    
    public boolean processWithTimeout(Shipment shipment) {
        try {
            // 1. 타임아웃
            if (reentrantLock.tryLock(5, TimeUnit.SECONDS)) {
                try {
                    doProcess(shipment);
                    return true;
                } finally {
                    reentrantLock.unlock();
                }
            }
            return false;   // 5초 내 못 얻음
        } catch (InterruptedException e) {
            // 2. 인터럽트 가능
            Thread.currentThread().interrupt();
            return false;
        }
    }
    
    private void doProcess(Shipment s) { }
}

8.7 자기 점검 답변

synchronized의 단점 3가지는?

:
1. 무한 대기:

  • 타임아웃 X
  • 데드락 회복 불가
  1. 인터럽트 불가:

    • BLOCKED 못 깨움
    • interrupt() 안 통함
  2. 공정성 X:

    • 순서 미정의
    • 기아 가능
  3. 극복:

    • ReentrantLock (Phase 5)
    • tryLock, lockInterruptibly, fair

9️⃣ 면접 + 자기 점검 + 마스터 50문항

9.1 면접 단골 질문 매핑

Q핵심 답변
모니터 락?모든 객체의 내장 락
intrinsic lock?고유 락 (내재)
락 획득?성공 RUNNABLE, 실패 BLOCKED
BLOCKED?락 대기 (Entry Set)
락 반환?종료 시 자동 (예외 포함)
100 스레드?1개 성공, 99개 BLOCKED
공정성?보장 X (비공정)
기아?특정 스레드 계속 못 받음
단점 3가지?무한 대기, 인터럽트 X, 비공정
Mark Word?객체 헤더의 락 정보

9.2 마스터 자기 점검 체크리스트

모니터 락

  • 정의 (intrinsic)
  • 모든 객체
  • 구성

객체 헤더

  • Mark Word
  • 락 상태 전이

락 획득

  • 성공 (RUNNABLE)
  • 실패 (BLOCKED)
  • monitorenter/exit

BLOCKED

  • Entry Set
  • 깨어남 (락 반납)
  • vs WAITING

자동 반환

  • 정상/예외
  • 데드락 방지

경쟁

  • 100 스레드
  • 직렬화
  • 경합 줄이기

공정성

  • 비공정
  • 기아

단점

  • 무한 대기
  • 인터럽트 X
  • 비공정

9.3 모니터 락 마스터 50문항

모니터 락 개념 (10문항)

Q1. 모니터 락? → 모든 객체 내장 락
Q2. intrinsic lock? → 고유 락
Q3. 모든 객체? → Object 상속
Q4. 모니터 구성? → 락 + 대기 집합
Q5. 객체 헤더? → Mark Word + Klass
Q6. Mark Word? → 락 정보
Q7. 락 상태 전이? → Biased→Lightweight→Heavyweight
Q8. Biased Lock? → 단일 스레드 최적화
Q9. 소유 스레드? → 현재 락 보유
Q10. 재진입 카운트? → 재획득 횟수

락 획득/반환 (10문항)

Q11. 진입 시? → monitorenter
Q12. 성공? → RUNNABLE
Q13. 실패? → BLOCKED
Q14. 종료 시? → monitorexit
Q15. 예외 시 반환? → 보장 (자동)
Q16. 자동 반환 장점? → unlock 불필요
Q17. Entry Set? → 락 대기 (BLOCKED)
Q18. Wait Set? → wait (WAITING)
Q19. BLOCKED 깨어남? → 락 반납
Q20. 인터럽트로 BLOCKED? → 안 깨어남

락 경쟁 (10문항)

Q21. 100 스레드? → 1 성공, 99 BLOCKED
Q22. 직렬화? → 하나씩
Q23. 경합? → 대기 많음
Q24. 높은 경합 영향? → 처리량 ↓
Q25. 경합 줄이기? → 락 분리, Atomic
Q26. Lock Striping? → 분할 락
Q27. lock-free? → Atomic (CAS)
Q28. 컨텍스트 스위칭? → 경합 시 ↑
Q29. 범위 최소화? → 경합 ↓
Q30. 무상태? → 경합 X

공정성 (10문항)

Q31. 공정성? → 획득 순서 = 대기 순서
Q32. synchronized 공정? → 비공정
Q33. 비공정? → 새치기 가능
Q34. 기아? → 계속 못 받음
Q35. 공정 락? → ReentrantLock(true)
Q36. 공정 단점? → 성능 ↓
Q37. 비공정 장점? → 처리량 ↑
Q38. barging? → 새치기
Q39. FIFO? → 공정 락
Q40. 순서 중요 시? → 공정 락

단점/극복 (10문항)

Q41. 단점 1? → 무한 대기
Q42. 단점 2? → 인터럽트 X
Q43. 단점 3? → 공정성 X
Q44. 무한 대기 문제? → 데드락 회복 X
Q45. 타임아웃? → tryLock (Phase 5)
Q46. 인터럽트 가능? → lockInterruptibly
Q47. 공정성? → ReentrantLock(true)
Q48. 극복 도구? → ReentrantLock
Q49. synchronized 장점? → 간단, 자동 반환
Q50. 언제 synchronized? → 단순, 짧은 임계

9.4 채점

50 / 50 → 모니터 락 마스터
45-49   → 거의 마스터
40-44   → 복습
< 40    → Unit 4.4 재학습

9.5 추가 심화 질문

Q1: Biased Locking 이 제거된 이유 (Java 15+)?

답:

  • JDK 15 부터 deprecated, 비활성화
  • 현대 앱에서 이점 적음
  • 복잡도 증가
  • 단일 스레드 가정 약화

Q2: spin lock 과 모니터?

답:

  • spin lock: 락 얻을 때까지 반복 (busy)
  • Lightweight Lock 에서 짧은 스핀
  • 그래도 안 되면 Heavyweight (모니터)
  • 적응형 스피닝

Q3: 모니터 락과 happens-before?

답:

  • monitorexit happens-before 다음 monitorenter
  • 가시성 보장
  • JMM 규칙
  • 락 해제 시 변경 flush

Q4: 데드락 4가지 조건?

답:

  • 상호 배제 (Mutual Exclusion)
  • 점유 대기 (Hold and Wait)
  • 비선점 (No Preemption)
  • 순환 대기 (Circular Wait)
  • 모두 충족 시 데드락

Q5: synchronized 와 메모리 배리어?

답:

  • monitorenter: acquire 배리어
  • monitorexit: release 배리어
  • 재정렬 방지
  • 가시성 보장

🎯 핵심 요약 — 3줄 정리

1. 모니터 락

  • 모든 객체의 내장 락 (intrinsic)
  • 획득 성공: RUNNABLE, 실패: BLOCKED
  • 종료 시 자동 반환 (예외 포함)

2. 경쟁과 공정성

  • 100 스레드 → 1 성공, 99 BLOCKED (직렬화)
  • 공정성 X (순서 미정의, 기아 가능)

3. 단점 3가지

  • 무한 대기 (타임아웃 X)
  • 인터럽트 불가
  • 공정성 X
  • → ReentrantLock 극복 (Phase 5)

📚 다음으로...

Unit 4.5 — volatile (메모리 가시성) (★ 마스터)

이번 Unit에서 모니터 락을 봤다면, 다음은 volatile (★ 마스터).

  • 메모리 가시성 문제
  • CPU 캐시
  • volatile 의 효과
  • 원자성 보장 X
  • synchronized 와 차이

Phase 4 진행 상황

🚀 Phase 4 — synchronized & volatile (★ 1차 정점)
  ✅ Unit 4.1 임계 영역과 동기화의 필요성
  ✅ Unit 4.2 synchronized 메서드
  ✅ Unit 4.3 synchronized 블록
  ✅ Unit 4.4 모니터 락 (★ 마스터) ← 여기
  ⏭ Unit 4.5 volatile (★ 마스터) — Phase 4 완주

4주차 누적 진행

✅ Phase 1 — 동시성의 기초 (4 Unit)
✅ Phase 2 — 4분면 매트릭스 (3 Unit)
✅ Phase 3 — 스레드 다루기 (5 Unit)
🚀 Phase 4 — synchronized & volatile (4/5 진행) ★ 1차 정점

총: 16/35 Unit
profile
Software Developer

0개의 댓글