item83 SeungminLee - JAVA-JIKIMI/EFFECTIVE-JAVA3 GitHub Wiki
item 83
์ง์ฐ ์ด๊ธฐํ๋ ์ ์คํ ์ฌ์ฉํ๋ผ
- ์ง์ฐ์ด๊ธฐํ๋ ํ๋์ ์ด๊ธฐํ ์์ ์ ๊ทธ ๊ฐ์ด ์ฒ์ ํ์ํ ๋๊น์ง ๋ฆ์ถ๋ ๊ธฐ๋ฒ
- ๊ฐ์ด ์ ํ ์ฐ์ด์ง ์์ผ๋ฉด ์ด๊ธฐํ๋ ๊ฒฐ์ฝ ์ผ์ด๋์ง ์์
- ์ด ๊ธฐ๋ฒ์ ์ ์ ํ๋์ ์ธ์คํด์ค ํ๋ ๋ชจ๋์ ์ฌ์ฉ ๊ฐ๋ฅ
- ์ฃผ๋ก ์ต์ ํ ์ฉ๋๋ก ์ฌ์ฉํ์ง๋ง, ํด๋์ค์ ์ธ์คํด์ค ์ด๊ธฐํ ๋ ๋ฐ์ํ๋ ์ํํ ์ํ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์์
lazy initalization /lazy loading /lazy evaluation
์ง์ฐ ์ด๊ธฐํ๋ฅผ ์ํ ์ต์ ์ ์กฐ์ธ "ํ์ํ ๋๊น์ง๋ ํ์ง ๋ง๋ผ"
์ง์ฐ ์ด๊ธฐํ๋ ์๋ ์ ๊ฒ์ด๋ค. ํด๋์ค ํน์ ์ธ์คํด์ค ์์ฑ ์์ ์ด๊ธฐํ ๋น์ฉ์ ์ค์ง๋ง ๊ทธ ๋์ ์ง์ฐ ์ด๊ธฐํํ๋ ํ๋์ ์ ๊ทผํ๋ ๋น์ฉ์ ์ปค์ง๋ค.
โ ํ๋๋ค ์ค ์ด๊ธฐํ๊ฐ ์ด๋ค์ง๋ ๋น์จ์ ๋ฐ๋ผ โ ์ค์ ์ด๊ธฐํ์ ๋๋ ๋น์ฉ์ ๋ฐ๋ผ โ ์ด๊ธฐํ๋ ๊ฐ ํ๋๋ฅผ ์ผ๋ง๋ ๋น๋ฒํ ํธ์ถํ๋ ์ ๋ฐ๋ผ ์ง์ฐ์ด๊ธฐํ๊ฐ ์ค์ ๋ก๋ ์ฑ๋ฅ์ ๋๋ ค์ง๊ฒ ํ ์๋ ์๋ค.
ํด๋์ค์ ์ธ์คํด์ค ์ค ๊ทธ ํ๋๋ฅผ ์ฌ์ฉํ๋ ์ธ์คํด์ค์ ๋น์จ์ด ๋ฎ์ ๋ฐ๋ฉด, ๊ทธ ํ๋๋ฅผ ์ด๊ธฐํํ๋ ๋น์ฉ์ด ํฌ๋ค๋ฉด ์ง์ฐ ์ด๊ธฐํ๊ฐ ์ ์ญํ ์ ํด์ค ๊ฒ์ด๋ค. (์ง์ฐ์ด๊ธฐํ๊ฐ ํจ๊ณผ๊ฐ ์๋์ง ์์๋ณด๊ธฐ ์ํด์๋ ์ ์ฉ ์ ํ์ ์ฑ๋ฅ์ ์ธก์ ํ๋ ๊ธธ ๋ฟ์ด๋ค)
๋ฉํฐ์ค๋ ๋ ํ๊ฒฝ์์์ ์ง์ฐ ์ด๊ธฐํ
๋ฉํฐ ์ค๋ ๋ ํ๊ฒฝ์์์ ์ง์ฐ ์ด๊ธฐํ๋ ๊น๋ค๋กญ๋ค. ์ง์ฐ ์ด๊ธฐํํ๋ ํ๋๋ฅผ ๋ ์ด์์ ์ค๋ ๋๊ฐ ๊ณต์ ํ๋ค๋ฉด ์ด๋ค ํํ๊ณ ๋ ๋ฐ๋์ ๋๊ธฐํ ํด์ผ ํ๋ค. ์ด๋ฅผ ์ด๊ธธ์ ์ฌ๊ฐํ ๋ฒ๊ทธ๋ฅผ ์ด๋ํ๋ค. ๋๋ถ๋ถ์ ์ํฉ์์ ์ผ๋ฐ์ ์ธ ์ด๊ธฐํ๊ฐ ์ง์ฐ ์ด๊ธฐํ ๋ณด๋ค ๋ซ๋ค๋ ๊ฒ์ ๊ธฐ์ตํ๊ณ ์์ ๋ฅผ ๋ณด๋๋ก ํ์.
์ผ๋ฐ์ ์ธ ์ธ์คํด์ค ํ๋๋ฅผ ์ ์ธํ ๋ ์ด๊ธฐํ๋ฅผ ํ๋ ์์
private final FieldType field = computeFieldValue();
์ง์ฐ์ด๊ธฐํ๋ก ์ธํด ์ด๊ธฐํ ์ํ์ฑ(initalization circularity)๊ฐ ๊นจ์ง ๊ฒ ๊ฐ์ผ๋ฉด 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;
}
์ ์ ํ๋๋ ํ๋์ ๋ฉ์๋ ์ ์ธ์ static ์ ์ ์ธํ๋ฉด ๋๊ฐ์ด ์ผ๋ฐ ์ด๊ธฐํ์ sunchronized๋ฅผ ์ฌ์ฉํ ์ด๊ธฐํ๋ฅผ ์ฌ์ฉํ ์ ์์ง๋ง ์ฑ๋ฅ์ ๊ณ ๋ คํ ๋ ์ธ๋ จ๋ ๋ฐฉ๋ฒ์ด ์๋ค.
์ ์ ํ๋ ์ง์ฐ์ด๊ธฐํ์๋ ์ง์ฐ ์ด๊ธฐํ ํ๋ ๊ด์ฉ๊ตฌ๋ฅผ ์ฌ์ฉํ์.
private static class FieldHolder {
static final FieldType field = computeFieldValue();
}
private static FieldType getField() { return FieldHolder.field; }
- getField๊ฐ ์ฒ์ ํธ์ถ๋๋ ์๊ฐ FieldHolder.field๊ฐ ์ฒ์ ์ฝํ๋ฉด์ FieldHolder ํด๋์ค ์ด๊ธฐํ๋ฅผ ์ด๋ฐํ๋ค.
- ๋ฉ์ง ์ : getField ๋ฉ์๋๊ฐ ํ๋์ ์ ๊ทผํ๋ฉด์ ๋๊ธฐํ๋ฅผ ์ ํ ํ์ง ์์ผ๋ ์ฑ๋ฅ์ด ๋๋ ค์ง ๊ฑฐ๋ฆฌ๊ฐ ์ ํ ์๋ค!
- ์ผ๋ฐ์ ์ธ VM์ ์ค์ง ํด๋์ค๋ฅผ ์ด๊ธฐํํ ๋๋ง ํ๋ ์ ๊ทผ์ ๋๊ธฐํ ํ๋ค โ ์ด๊ธฐํ๊ฐ ๋๋ ํ์๋ VM์ด ๋๊ธฐํ ์ฝ๋๋ฅผ ์ ๊ฑฐํ๋ค โ ์ดํ ์๋ฌด๋ฐ ๊ฒ์ฌ๋ ๋๊ธฐํ ์์ด ํ๋์ ์ ๊ทผํ๊ฒ ๋๋ค.
์ฑ๋ฅ ๋๋ฌธ์ ์ธ์คํด์ค ํ๋๋ฅผ ์ง์ฐ ์ด๊ธฐํํด์ผ ํ๋ค๋ฉด ์ด์ค๊ฒ์ฌ ๊ด์ฉ๊ตฌ๋ฅผ ์ฌ์ฉํ๋ผ
์ด ๊ด์ฉ๊ตฌ๋ ์ด๊ธฐํ๋ ํ๋์ ์ ๊ทผํ ๋์ ๋๊ธฐํ ๋น์ฉ์ ์์ ์ค๋ค. ํ๋์ ๊ฐ์ ๋ ๋ฒ ๊ฒ์ฌํ๋ ๋ฐฉ์์ผ๋ก, ํ ๋ฒ์ ๋๊ธฐํ ์์ด ๊ฒ์ฌํ๊ณ (ํ๋๊ฐ ์์ง ์ด๊ธฐํ ๋์ง ์์๋ค๋ฉด) ๋ ๋ฒ์งธ๋ ๋๊ธฐํํ์ฌ ๊ฒ์ฌํ๋ค. ๋ ๋ฒ์งธ ๊ฒ์ฌ์์๋ ํ๋๊ฐ ์ด๊ธฐํ๋์ง ์์์ ๋๋ง ํ๋๋ฅผ ์ด๊ธฐํํ๋ค.
โ ํ๋๊ฐ ์ด๊ธฐํ๋ ํ๋ก๋ ๋๊ธฐํํ์ง ์์ผ๋ฏ๋ก ํด๋น ํ๋๋ ๋ฐ๋์ volatile๋ก ์ ์ธํด์ผ ํ๋ค.
private volatile FieldType field;
private FieldType getField() {
FieldType result = field;
if (result != null ) // ์ฒซ ๋ฒ์งธ ๊ฒ์ฌ (๋ฝ X)
return result;
synchronized(this) {
if (field == null) // ๋ ๋ฒ์งธ ๊ฒ์ฌ (๋ฝ O)
field = computeFieldValue();
return field;
}
}
- result ์ง์ญ๋ณ์๊ฐ ํ์ํ ์ด์ ๋ ๋ฌด์์ธ๊ฐ? ์ด ๋ณ์๊ฐ ์ด๋ฏธ ์ด๊ธฐํ๋ ์ผ๋ฐ์ ์ธ ์ํฉ์์ ๊ทธ ํ๋๋ฅผ ๋ฑ ํ ๋ฒ๋ง ์ฝ๋๋ก ๋ณด์ฅํ๋ ์ญํ ์ ํ๋ค. ๋ฐ๋์ ํ์ํ์ง๋ ์์ง๋ง ์ฑ๋ฅ์ ๋์ฌ์ฃผ๋ ์ฐ์ํ ๋ฐฉ๋ฒ์ด๋ค.
- ์ด์ค๊ฒ์ฌ ๊ด์ฉ๊ตฌ๋ฅผ ์ ์ ํ๋์๋ ์ ์ฉํ ์ ์์ผ๋ ์ง์ฐ ์ด๊ธฐํ ํ๋ ๊ด์ฉ๊ตฌ๊ฐ ๋ ๋ซ๋ค.
- ๋ณ์ข : ๋๋๋ก ๋ฐ๋ณตํด์ ์ด๊ธฐํํด๋ ์๊ด์๋ ์ธ์คํด์ค ํ๋๋ฅผ ์ง์ฐ ์ด๊ธฐํํด์ผ ํ๋ค๋ฉด ๋ ๋ฒ์งธ ๊ฒ์ฌ๋ฅผ ์๋ตํ ์ ์๋ค. (๋จ์ผ ๊ฒ์ฌ ๊ด์ฉ๊ตฌ)
๋จ์ผ ๊ฒ์ฌ ๊ด์ฉ๊ตฌ
private volatile FieldType field;
private FieldType getField() {
FieldType result = field;
if (result == null)
field = result = computeFieldValue();
return result;
}
-
์ด๋ฒ ์์ดํ ์์ ์ด์ผ๊ธฐํ ๋ชจ๋ ์ด๊ธฐํ ๊ธฐ๋ฒ์ ๊ธฐ๋ณธ ํ์ ํ๋์ ๊ฐ์ฒด ์ฐธ์กฐ ํ๋ ๋ชจ๋์ ์ ์ฉํ ์ ์๋ค. ์ด์ค๊ฒ์ฌ์ ๋จ์ผ๊ฒ์ฌ ๊ด์ฉ๊ตฌ๋ฅผ ์์น ๊ธฐ๋ณธ ํ์ ํ๋์ ์ ์ฉํ๋ค๋ฉด ํ๋์ ๊ฐ์ null ๋์ (์ซ์ ๊ธฐ๋ณธ ํ์ ๋ณ์์ ๊ธฐ๋ณธ๊ฐ์ธ) 0๊ณผ ๋น๊ตํ๋ฉด ๋๋ค.
-
๋ชจ๋ ์ค๋ ๋๊ฐ ํ๋์ ๊ฐ์ ๋ค์ ๊ณ์ฐํด๋ ์๊ด์๊ณ ํ๋์ ํ์ ์ด long๊ณผ double์ ์ ์ธํ ๋ค๋ฅธ ๊ธฐ๋ณธ ํ์ ์ด๋ผ๋ฉด ๋จ์ผ๊ฒ์ฌ์ ํ๋ ์ ์ธ์์ volatile์ ์์ ๋ ๋๋ค. (racy single-check)
(long ๊ณผ double์ ๊ผญ volatile์ ์จ์ผ ํ๋ ์ด์ : ํ๋ฒ์ 32bits์ฉ ์ฝ๊ณ ์ฐ๋๋ฐ long๊ณผ double์ 8byte ๋ผ์ 32 bits๋ ํ ์ฐ๋ ๋์, ๋๋จธ์ง 32bits ๋ ๋ค๋ฅธ ์ฐ๋ ๋์ ์จ์ง ์ ์๋ค. (word taering)
-
racy single-check ์ ์ด๋ค ํ๊ฒฝ์์๋ ํ๋ ์ ๊ทผ ์๋๋ฅผ ๋์ฌ์ฃผ์ง๋ง, ์ด๊ธฐํ๊ฐ ์ค๋ ๋๋น ์ต๋ ํ ๋ฒ ๋ ์ด๋ค์ง ์ ์๋ ์์ฃผ ์ด๋ก์ ์ธ ๊ธฐ๋ฒ์ผ๋ก, ์ ์ฐ์ง ์๋๋ค.
ํต์ฌ ์ ๋ฆฌ
- ๋๋ถ๋ถ์ ํ๋๋ ์ง์ฐ์ํค์ง ๋ง๊ณ ๊ณง๋ฐ๋ก ์ด๊ธฐํํด์ผ ํ๋ค.
- ์ฑ๋ฅ ๋๋ฌธ์ ์ง์ฐ์ด๊ธฐํ๋ฅผ ๊ผญ ์จ์ผ ํ๋ค๋ฉด ์ฌ๋ฐ๋ฅธ ์ง์ฐ ์ด๊ธฐํ ๊ธฐ๋ฒ์ ์ฌ์ฉํ์.
- ์ธ์คํด์ค ํ๋์๋ ์ด์ค๊ฒ์ฌ ๊ด์ฉ๊ตฌ๋ฅผ ์ฌ์ฉํ์.
- ์ ์ ํ๋์๋ ์ง์ฐ ์ด๊ธฐํ ํ๋ ํด๋์ค ๊ด์ฉ๊ตฌ๋ฅผ ์ฌ์ฉํ์.
- ๋ฐ๋ณตํด์ ์ด๊ธฐํํด๋ ๊ด์ฐฎ์ ์ธ์คํด์ค ํ๋์๋ ๋จ์ผ ๊ฒ์ฌ ๊ด์ฉ๊ตฌ ์ฌ์ฉ์ ๊ณ ๋ คํด๋ณด์.