Java 동기화(synchronized) 내부 동작 메커니즘 분석

synchronized 동작 원리

Java의 synchronized 키워드는 메서드 또는 코드 블록에 적용되어 다중 스레드 환경에서 한 번에 하나의 스레드만 접근할 수 있도록 보장합니다.

메서드 동기화

class SyncExample {
    public synchronized void syncMethod() {
        // 동기화 로직
    }
}

// 인스턴스 메서드 동등 표현
class SyncExample {
    public void syncMethod() {
        synchronized(this) {
            // 동기화 로직
        }
    }
}

// 정적 메서드 동기화
class SyncExample {
    public static synchronized void staticSync() {
        // 동기화 로직
    }
}

// 정적 메서드 동등 표현
class SyncExample {
    public static void staticSync() {
        synchronized(SyncExample.class) {
            // 동기화 로직
        }
    }
}

객체 동기화 예제

class Counter {
    private static int total = 0;
    private static final Object lock = new Object();
    
    public static void main(String[] args) throws InterruptedException {
        Thread adder = new Thread(() -> {
            for (int i = 0; i < 5000; i++) {
                synchronized (lock) {
                    total++;
                }
            }
        });
        
        Thread subtractor = new Thread(() -> {
            for (int i = 0; i < 5000; i++) {
                synchronized (lock) {
                    total--;
                }
            }
        });
        
        adder.start();
        subtractor.start();
        adder.join();
        subtractor.join();
        System.out.println("Result: " + total);
    }
}

편향 락(Biased Lock)

경쟁이 없는 초기 상태에서 적용되는 최적화 기법입니다. 첫 CAS 연산으로 스레드 ID를 객체 헤더에 저장한 후, 동일 스레드 접근 시 추가 작업 없이 접근이 허용됩니다.

  • 객체 생성 시 편향 락 활성화: Mark Word(0x05)
  • 기본 지연 시간 존재(-XX:BiasedLockingStartupDelay=0으로 비활성화 가능)
  • hashCode() 호출 시 편향 락 해제
  • 다른 스레드의 객체 사용 시 경량 락으로 전환
  • 대기/알림 메서드(wait()/notify()) 호출 시 무게 락으로 전환

경량 락(Lightweight Lock)

스레드 간 경쟁이 시간적으로 겹치지 않는 경우 사용됩니다.

  1. 스레드 스택에 Lock Record 생성
  2. CAS로 객체 Mark Word 업데이트 시도
  3. 성공 시 객체 헤더에 락 기록(00 상태)
  4. 실패 시 경쟁 발생(락 확장) 또는 재진입
  5. 잠금 해제 시 CAS로 Mark Word 복원

락 확장(Lock Inflation)

경량 락 경쟁 발생 시 무게 락(Heavyweight Lock)으로 전환됩니다.

  • Monitor 객체 생성 및 연결
  • 경쟁 스레드는 EntryList에서 차단(BLOCKED)
  • 원본 스레드 해제 시 Monitor의 Owner 초기화 및 대기 스레드 깨움

스핀 최적화(Spin Optimization)

무게 락 경쟁 시 CPU 회전으로 차단 회피를 시도합니다.

  • 단일 코어 CPU에서는 비효율적
  • Java 6 이후 적응형 스핀 구현
  • 성공 경험에 따라 스핀 횟수 자동 조정
  • Java 7+에서는 사용자 제어 불가

락 업그레이드 과정

무경쟁 → 편향 락 → (경쟁 발생 시) 경량 락 → 무게 락

태그: java 스레드-안전성 동기화-메커니즘 락-최적화 JVM-내부

6월 4일 18:05에 게시됨