Skip to content

[아이템 83] 지연 초기화는 신중히 사용하라 #93

@Ori-Gui

Description

@Ori-Gui

📌 [아이템 83] 지연 초기화는 신중히 사용하라

✨ 핵심 내용

  • **지연 초기화(Lazy Initialization)**는 값이 실제로 사용될 때까지 객체 생성이나 계산을 미루는 기법
  • 성능 최적화나 초기화 순환 문제 해결이 목적이지만, 잘못 사용하면 성능 저하 및 버그로 이어짐
  • 특히 멀티스레드 환경에서는 반드시 동기화가 필요

✔ 일반적인 초기화

private final FieldType field = computeFieldValue();

synchronized 접근자 방식 (스레드 안전한 지연 초기화)

private FieldType field;

private synchronized FieldType getField() {
    if (field == null)
        field = computeFieldValue();
    return field;
}

✔ 정적 필드에 대한 지연 초기화 홀더 클래스 패턴

private static class FieldHolder {
    static final FieldType field = computeFieldValue();
}

private static FieldType getField() {
    return FieldHolder.field;
}

✔ 인스턴스 필드에 대한 이중 검사(Double-Check) 패턴

private volatile FieldType field;

private FieldType getField() {
    FieldType result = field;
    if (result != null)
        return result;
    synchronized (this) {
        if (field == null)
            field = computeFieldValue();
        return field;
    }
}

✔ 단일 검사(Single-Check) 패턴 (중복 초기화 허용)

private volatile FieldType field;

private FieldType getField() {
    FieldType result = field;
    if (result == null)
        field = result = computeFieldValue();
    return result;
}

💡 새롭게 알게 된 점

  • 지연 초기화가 좋은 줄 알았지만, 실제로는 초기화 비용, 호출 빈도, 사용 비율 등을 따져야 하며, 그에 따라 일반 초기화가 더 나은 경우가 많다는 것을 배웠다.
  • 지연 초기화 홀더 클래스 패턴은 처음 접했는데, static class 초기화 타이밍을 JVM이 보장해주므로 비동기적 접근에도 완벽히 안전하다는 점이 인상 깊었다.

📚 정리

  • 지연 초기화는 필요할 때만, 그리고 안정적인 방식으로 사용해야 한다.
  • 성능 때문에 지연 초기화를 하고 싶다면 다음 가이드를 따르자:
    • 정적 필드 → 지연 초기화 홀더 클래스 패턴 사용
    • 인스턴스 필드 → 이중 검사 패턴 사용 (필드는 volatile)
    • 초기화 중복 허용 → 단일 검사 패턴 고려
  • 초기화 비용이 크고 사용 비율이 낮은 필드에만 지연 초기화를 적용하는 것이 현실적이다.

📢 댓글로 각자의 학습 내용을 공유해주세요!

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions