item 83 JungHyunLyoo - JAVA-JIKIMI/EFFECTIVE-JAVA3 GitHub Wiki

์ง€์—ฐ ์ดˆ๊ธฐํ™”(lazy initialization)๋ž€?

ํ•„๋“œ์˜ ์ดˆ๊ธฐํ™” ์‹œ์ ์„ ๊ทธ ๊ฐ’์ด ์ฒ˜์Œ ํ•„์š”ํ•  ๋•Œ๊นŒ์ง€ ๋Šฆ์ถ”๋Š” ๊ธฐ๋ฒ•.

์ง€์—ฐ ์ดˆ๊ธฐํ™”๋Š” ์–‘๋‚ ์˜ ๊ฒ€์ด๋‹ค. ์ตœ๋Œ€ํ•œ ์ด ๊ธฐ๋ฒ•์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๊ฒŒ ์ข‹๋‹ค(item67)

์ธ์Šคํ„ด์Šค ์ƒ์„ฑ ์‹œ์˜ ์ดˆ๊ธฐํ™” ๋น„์šฉ์€ ์ค„์ง€๋งŒ, ๋Œ€์‹  ์ง€์—ฐ ์ดˆ๊ธฐํ™”ํ•˜๋Š” ํ•„๋“œ์— ์ ‘๊ทผํ•˜๋Š” ๋น„์šฉ์€ ์ปค์ง€๊ธฐ ๋•Œ๋ฌธ.

ํ•˜์ง€๋งŒ ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค ์ค‘ ๊ทธ ํ•„๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ธ์Šคํ„ด์Šค์˜ ๋น„์œจ์ด ๋‚ฎ์€ ๋ฐ˜๋ฉด,

๊ทธ ํ•„๋“œ๋ฅผ ์ดˆ๊ธฐํ™”ํ•˜๋Š” ๋น„์šฉ์ด ํฌ๋‹ค๋ฉด ์ง€์—ฐ ์ดˆ๊ธฐํ™”๋ฅผ ์‚ฌ์šฉํ•˜๋Š”๊ฒŒ ์ข‹๋‹ค.

๊ทธ๋ฆฌ๊ณ  ์ง€์—ฐ ์ดˆ๊ธฐํ™”ํ•˜๋Š” ํ•„๋“œ๋ฅผ ๋‘˜ ์ด์ƒ์˜ ์Šค๋ ˆ๋“œ๊ฐ€ ๊ณต์œ ํ•œ๋‹ค๋ฉด,

์–ด๋–ค ํ˜•ํƒœ๋กœ๋Š” ๋ฐ˜๋“œ์‹œ ๋™๊ธฐํ™”ํ•ด์•ผ ํ•œ๋‹ค. (item78)

๋ฐฉ์‹ 1. ์ธ์Šคํ„ด์Šค ํ•„๋“œ์˜ ์ง€์—ฐ ์ดˆ๊ธฐํ™” - synchronized ์ ‘๊ทผ์ž ๋ฐฉ์‹

์ง€์—ฐ ์ดˆ๊ธฐํ™”๊ฐ€ ์ดˆ๊ธฐํ™” ์ˆœํ™˜์„ฑ(initialization circularity)์„ ๊นจ๋œจ๋ฆด ๊ฒƒ ๊ฐ™์œผ๋ฉด

synchronized๋ฅผ ๋‹จ ์ ‘๊ทผ์ž๋ฅผ ์‚ฌ์šฉํ•˜์ž. ์•„๋ž˜ ์ฝ”๋“œ๋Š” ์ •์  ํ•„๋“œ์—๋„ ๋˜‘๊ฐ™์ด ์‚ฌ์šฉ๊ฐ€๋Šฅํ•˜๋‹ค

private FieldType field;

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

๋ฐฉ์‹ 2. ์ •์  ํ•„๋“œ์šฉ ์ง€์—ฐ ์ดˆ๊ธฐํ™” ํ™€๋” ํด๋ž˜์Šค ๊ด€์šฉ๊ตฌ

์„ฑ๋Šฅ ๋•Œ๋ฌธ์— ์ •์  ํ•„๋“œ๋ฅผ ์ง€์—ฐ ์ดˆ๊ธฐํ™”ํ•ด์•ผ ํ•œ๋‹ค๋ฉด

์ง€์—ฐ ์ดˆ๊ธฐํ™” ํ™€๋” ํด๋ž˜์Šค(lazy initialization holder class) ๊ด€์šฉ๊ตฌ๋ฅผ ์‚ฌ์šฉํ•˜์ž

ํด๋ž˜์Šค๋Š” ํด๋ž˜์Šค๊ฐ€ ์ฒ˜์Œ ์“ฐ์ผ ๋•Œ ๋น„๋กœ์†Œ ์ดˆ๊ธฐํ™”๋œ๋‹ค๋Š” ํŠน์„ฑ์„ ์ด์šฉํ•œ ๊ด€์šฉ๊ตฌ๋‹ค.

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

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

getField๊ฐ€ ์ฒ˜์Œ ํ˜ธ์ถœ๋˜๋Š” ์ˆœ๊ฐ„ FieldHolder.field๊ฐ€ ์ฒ˜์Œ ์ฝํžˆ๋ฉด์„œ

๋น„๋กœ์†Œ FieldHolder ํด๋ž˜์Šค ์ดˆ๊ธฐํ™”๋ฅผ ์ด‰๋ฐœํ•œ๋‹ค.

์ด ๊ด€์šฉ๊ตฌ์˜ ๋ฉ‹์ง„ ์ ์€ getField ๋ฉ”์„œ๋“œ๊ฐ€ ํ•„๋“œ์— ์ ‘๊ทผํ•˜๋ฉด์„œ ๋™๊ธฐํ™”๋ฅผ ์ „ํ˜€ ํ•˜์ง€ ์•Š์œผ๋‹ˆ

์„ฑ๋Šฅ์ด ๋А๋ ค์ง€์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. ์ผ๋ฐ˜์ ์ธ VM์€ ์˜ค์ง ํด๋ž˜์Šค๋ฅผ ์ดˆ๊ธฐํ™”ํ•  ๋•Œ๋งŒ

ํ•„๋“œ ์ ‘๊ทผ์„ ๋™๊ธฐํ™”ํ•  ๊ฒƒ์ด๋‹ค. ํด๋ž˜์Šค ์ดˆ๊ธฐํ™”๊ฐ€ ๋๋‚œ ํ›„์—๋Š” VM์ด ๋™๊ธฐํ™” ์ฝ”๋“œ๋ฅผ ์ œ๊ฑฐํ•˜์—ฌ,

๊ทธ ๋‹ค์Œ๋ถ€ํ„ฐ๋Š” ์•„๋ฌด๋Ÿฐ ๊ฒ€์‚ฌ๋‚˜ ๋™๊ธฐํ™” ์—†์ด ํ•„๋“œ์— ์ ‘๊ทผํ•˜๊ฒŒ ๋œ๋‹ค.

๋ฐฉ์‹ 3. ์ธ์Šคํ„ด์Šค ํ•„๋“œ์šฉ ์ง€์—ฐ ์ดˆ๊ธฐํ™” ์ด์ค‘๊ฒ€์‚ฌ ๊ด€์šฉ๊ตฌ

์„ฑ๋Šฅ ๋•Œ๋ฌธ์— ์ธ์Šคํ„ด์Šค ํ•„๋“œ๋ฅผ ์ง€์—ฐ ์ดˆ๊ธฐํ™”ํ•ด์•ผ ํ•œ๋‹ค๋ฉด ์ด์ค‘๊ฒ€์‚ฌ(double-check) ๊ด€์šฉ๊ตฌ๋ฅผ ์‚ฌ์šฉํ•˜๋ผ.

private volatile FieldType field;

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

    synchronized (this) {
        if (field == null) {
            field = coputeFieldValue();
        }
        return field;
    }
}

์ด ๊ด€์šฉ๊ตฌ๋Š” ์ดˆ๊ธฐํ™”๋œ ํ•„๋“œ์— ์ ‘๊ทผํ•  ๋•Œ์˜ ๋™๊ธฐํ™” ๋น„์šฉ์„ ์—†์• ์ค€๋‹ค (item79)

๊ทธ๋ฆฌ๊ณ  ํ•„๋“œ์˜ ๊ฐ’์„ ๋‘๋ฒˆ ๊ฒ€์‚ฌํ•˜๋Š” ๋ฐฉ์‹์ธ๋ฐ, ํ•œ ๋ฒˆ์€ ๋™๊ธฐํ™” ์—†์ด ๊ฒ€์‚ฌํ•˜๊ณ 

(ํ•„๋“œ๊ฐ€ ์•„์ง ์ดˆ๊ธฐํ™”๋˜์ง€ ์•Š์•˜๋‹ค๋ฉด) ๋‘ ๋ฒˆ์งธ๋Š” ๋™๊ธฐํ™”ํ•˜์—ฌ ๊ฒ€์‚ฌํ•œ๋‹ค.

ํ•„๋“œ๊ฐ€ ์ดˆ๊ธฐํ™”๋œ ํ›„๋กœ๋Š” ๋™๊ธฐํ™”ํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ํ•ด๋‹น ํ•„๋“œ๋Š” ๋ฐ˜๋“œ์‹œ volatile๋กœ ์„ ์–ธํ•ด์•ผ ํ•œ๋‹ค. (item78)