Growth-Collectors / effective-java

repository for effective java study
3 stars 2 forks source link

아이템 83. 지연 초기화는 신중히 사용하라 #85

Open HanaHww2 opened 1 year ago

yeGenieee commented 1 year ago

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

지연 초기화

지연 초기화 특징

초기화 방법

1. 일반적인 초기화 방법

private final FieldType field = computeFieldValue();

2. 지연 초기화 - synchronized 한정자

초기화 순환성

  • Class A의 생성자가 Class B의 인스턴스를 생성하고,
  • Class B가 Class C의 인스턴스를 생성하고,
  • Class C가 Class A의 인스턴스를 생성하는 경우
private FieldType field;
private synchronized FieldType getField() {
    if (field == null) {
        field = computeFieldValue();
    } 
    return field;
}

3. 정적 필드 지연 초기화 홀더 클래스 관용구

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

- `getField()` 메서드가 호출되면, `FieldHolder.field` 가 읽히면서 `FieldHolder` 클래스 초기화를 한다
- 동기화를 하지 않기 때문에 성능이 느려질 걱정이 없다는 장점을 가진다

### 4. 인스턴스 필드 지연 초기화 이중검사 관용구
- 성능 때문에 인스턴스 필드를 지연 초기화해야 한다면, 이중검사 관용구를 사용하자
- 초기화된 필드에 접근할 때의 동기화 비용을 없애준다
```java
private volatile FieldType field;

private FieldType getField() {
    FieldType result = field;

    // 첫번째 검사 (Lock 사용 안함)
    if (result != null) {
        return result;
    }

    // 두번째 검사 (Lock 사용)
    synchronized(this) {
        if (field == null) {
            field = computeFieldValue();
        }
        return field;
    }
}

5. 이중검사 관용구의 변종 - 단일 검사 관용구

private FieldType getField() { FieldType result = field;

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

}


### 6. 이중검사 관용구의 변종 - 짜릿한 단일 검사 관용구 (racy single-check)
- 모든 스레드가 필드의 값을 다시 계산해도 상관없고, 필드의 타입이 long과 double을 제외한 다른 기본 타입이라면, 필드 선업에서 `volatile` 한정자를 없애도 된다
```java
private FieldType field;

private FieldType getField() {
    FieldType result = field;

    if (result == null) {
        field = result = computerFieldValue();
    }
    return result;
}