๐จ 05. ์ฑ๊ธํด ํจํด
๐ซย ํ๋๋ฟ์ธ ํน๋ณํ ๊ฐ์ฒด ๋ง๋ค๊ธฐ, ์ฑ๊ธํด ํจํด
๊ณ ์ ๊ฐ์ฒด ์ธ์คํด์ค 1๊ฐ ๋ง๋๋ ๋ฐฉ๋ฒ์ 1๊ฐ ์ฅ์ ๊ฑธ์ณ์ ๋ฐฐ์ด๋ค๊ณ ์?
์ฑ๊ธํด ํจํด์ ํน์ ํด๋์ค์ ๊ฐ์ฒด ์ธ์คํด์ค๊ฐ ํ๋๋ง ๋ง๋ค์ด์ง๋๋ก ํด ์ฃผ๋ ํจํด์ด๋ค. ์ฑ๊ธํด ํจํด์ ์ฌ์ฉํ๋ฉด ์ ์ญ ๋ณ์๋ฅผ ์ฌ์ฉํ ๋์ ๋ง์ฐฌ๊ฐ์ง๋ก ๊ฐ์ฒด ์ธ์คํด์ค๋ฅผ ์ด๋์๋ ์ง ์ก์ธ์คํ ์ ์๊ฒ ๋ง๋ค ์ ์์ผ๋ฉฐ, ์ ์ญ ๋ณ์๋ฅผ ์ธ ๋์ ๋จ์ (์ ํ๋ฆฌ์ผ์ด์ ์ด ๋๋ ๋๊น์ง ํ ๋ฒ๋ ์ฐ์ง ์๋ -๊ดํ ์์๋ง ์ก์๋จน๋- ์ธ๋ฐ์๋ ๊ฐ์ฒด๊ฐ ์๊ธฐ๋ ๋ฌธ์ ๋ฑ)์ ๊ฐ์ํ ํ์๋ ์๋ค. ์ฑ๊ธํด ํจํด์ ์ฌ์ฉํ๋ฉด ํ์ํ ๋๋ง ๊ฐ์ฒด๋ฅผ ๋ง๋ค ์ ์๊ธฐ ๋๋ฌธ์ด๋ค.
โ์ด๋ป๊ฒ ํ๋ฉด ํ ํด๋์ค์ ์ธ์คํด์ค๋ฅผ ๋ ๊ฐ ์ด์ ๋ง๋ค์ง ์๊ฒ ํ์ง?โ
๐ซย ๊ณ ์ ์ ์ธ ์ฑ๊ธํด ํจํด ๊ตฌํ๋ฒ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Singleton {
// ๊ณ ์ ๋ ๋จ ํ๋์ ์ธ์คํด์ค๋ฅผ ์ ์ฅํ๋ ์ ์ ๋ณ์
private static Singleton uniqueInstance = null;
// ์ธ๋ถ์์ new Singleton() ํ์ง ๋ชปํ๋๋ก ์์ฑ์๋ฅผ private์ผ๋ก ์ ์ธ
private Singleton() {
// ์์ฑ์ ๋ด๋ถ ๋ก์ง
}
// ์ธ๋ถ์์ ์ธ์คํด์ค๋ฅผ ๊ฐ์ ธ๊ฐ๋ ์ ์ผํ ๋ฐฉ๋ฒ
public static Singleton getInstance() {
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
// ๊ธฐํ ๋ฉ์๋
}
| ๋ผ์ธ | ์ค๋ช |
|---|---|
| private static uniqueInstance | ์ด ํด๋์ค์ ์ ์ผํ ์ธ์คํด์ค๋ฅผ ์ ์ฅํ๋ ์ ์ ๋ณ์. null๋ก ์ด๊ธฐํํด์ ์์ง ์์ฑ๋์ง ์์์์ ๋ํ๋. |
| private Singleton() | ์์ฑ์๋ฅผ private์ผ๋ก ์ ์ธํด์ ์ธ๋ถ์์ new Singleton()์ ํ์ง ๋ชปํ๊ฒ ํจ. ์ค์ง ํด๋์ค ๋ด๋ถ์์๋ง ์์ฑ ๊ฐ๋ฅ. |
| static getInstance() | ์ธ์คํด์ค๋ฅผ ์์ฑํ๊ฑฐ๋ ๋ฐํํ๋ ๋ฉ์๋. ์ธ์คํด์ค๊ฐ ์์ผ๋ฉด ์๋ก ๋ง๋ค๊ณ , ์์ผ๋ฉด ๊ธฐ์กด ๊ฒ์ ๋ฐํ. |
ํต์ฌ ์์ฝ:
- ์ธ๋ถ์์ ์ง์ ์ธ์คํด์ค๋ฅผ ๋ง๋ค ์ ์๊ฒ ํ๊ณ
- ๋ด๋ถ์์ ๋จ ํ ๋ฒ๋ง ์์ฑ๋๋๋ก ์ ํ
- ์ธ์ ๋ ๋์ผํ ๊ฐ์ฒด์ ์ ๊ทผ ๊ฐ๋ฅํ๋๋ก static ๋ฉ์๋๋ก ๋ ธ์ถ
๐ค ํจํด ์ง์ค ์ธํฐ๋ทฐ - ์ฑ๊ธํด ๊ฐ์ฒด์ ์ฌ๊ฒฝ ๊ณ ๋ฐฑ
์ธํฐ๋ทฐ ์์ฝ:
- ๋๋ ํ๋ก๊ทธ๋จ์์ ๋จ ํ๋๋ฟ์ธ ๊ฐ์ฒด๋ค
- ๋ ์ง์คํธ๋ฆฌ ์ค์ ์ด ๋ด๊ฒจ ์๋ ๊ฐ์ฒด๊ฐ ์ฌ๋ฌ ๊ฐ ์๋ค๋ฉด ์๋ก ๋ค๋ฅธ ์ค์ ๋ด์ญ๋ ์ฌ๋ฌ ๊ฐ ์๋ค๋ ๋ง์ด ๋๋ค. ํ์ง๋ง ์ฑ๊ธํด์ ์ฌ์ฉํ๋ฉด ํ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ค์ด์๋ ์ด๋ค ๊ฐ์ฒด์์๋ ๊ฐ์ ์์์ ํ์ฉํ ์ ์๋ค.
- ๋๋ฅผ ๋ง๋ค๊ธฐ ์ํด ์์ฑ์๋ฅผ private์ผ๋ก ์จ๊ฒผ์
- public์ผ๋ก ์ง์ ๋ ์์ฑ์๊ฐ ์๋ค = ์ธ๋ถ์์ ์ธ์คํด์ค๋ฅผ ์์ฑํ ์ ์๋๋ก private ์์ฑ์๋ง ์กด์ฌํ๋ค.
- ๋จ ํ๋์ ์ธ์คํด์ค๋ง ๊ฐ์ง๋๋ก ์ฒ ์ ํ ํต์ ๋์ด ์์
- ํด๋์ค๊ฐ ์ธ์คํด์ค๋ฅผ ์ค์ง ํ๋๋ง ์์ฑํ๊ฒ ๋ง๋ค๊ณ , ๋ค๋ฅธ ๊ฒฝ๋ก๋ก๋ ์ ๋๋ก ์ ์ธ์คํด์ค๋ฅผ ๋ง๋ค ์ ์๋๋ก ๊ฐ์ ํ๋ค.
- ์ฑ๊ธํด ๊ฐ์ฒด๊ฐ ํ์ํ ๊ฒฝ์ฐ new Singleton() ๊ฐ์ ๋ฐฉ์์ผ๋ก ์๋ก์ด ๊ฐ์ฒด๋ฅผ ๋ง๋ค์ง ๋ชปํ๊ฒ ํ๊ณ , getInstance()๋ผ๋ ์ ์ ๋ฉ์๋๋ฅผ ํธ์ถํ๋ค.
๐ซย ์ด์ฝ๋ฆฟ ๋ณด์ผ๋ฌ ์ฝ๋ ์ดํด๋ณด๊ธฐ
์์ฆ์ ๋๋ค์์ ์ด์ฝ๋ฆฟ ๊ณต์ฅ์์ ์ด์ฝ๋ฆฟ์ ๋์ด๋ ์ฅ์น(์ดํ โ์ด์ฝ๋ฆฟ ๋ณด์ผ๋ฌโ๋ก ์ง์นญ)๋ฅผ ์ปดํจํฐ๋ก ์ ์ดํ๋ค. ์ด์ฝ๋ฆฟ ๋ณด์ผ๋ฌ๋ ์ด์ฝ๋ฆฟ๊ณผ ์ฐ์ ๋ฅผ ๋ฐ์์ ๋์ด๊ณ ์ด์ฝ๋ฐ๋ฅผ ๋ง๋๋ ๋จ๊ณ๋ก ๋๊ฒจ์ค๋ค. ์๋์๋ ์ต์ ํ ์ด์ฝ๋ฆฟ ๋ณด์ผ๋ฌ๋ฅผ ์ ์ดํ๋ ํด๋์ค๊ฐ ๋์ ์๋ค.
์ด์ฝ๋ฆฟ ๊ณต์ฅ์์ ์ฌ์ฉํ๋ ์ฅ์น์ธ ์ด์ฝ๋ฆฟ ๋ณด์ผ๋ฌ๋ ๋ค์์ ์์๋ฅผ ๋ฐ๋ผ ์๋ํ๋ค.
- ์ด์ฝ๋ฆฟ๊ณผ ์ฐ์ ๋ฅผ ์ฑ์ด๋ค
- ๋ณด์ผ๋ฌ๋ฅผ ๊ฐ์ดํด ๋์ธ๋ค
- ๋ค ๋์ ์ฌ๋ฃ๋ฅผ ๋ค์ ๊ณต์ ์ธ ์ด์ฝ๋ฐ ๋ง๋ค๊ธฐ๋ก ๋๊ธด๋ค
๋ค์๊ณผ ๊ฐ์ ์ค์๋ ๋ง๋๋ค.
- ์์ง ๋์ง ์์ ์ฌ๋ฃ 500๊ฐค๋ฐ์ ๊ทธ๋ฅ ํ๋ ค ๋ฒ๋ฆฐ๋ค. โ
- ๋ณด์ผ๋ฌ๊ฐ ๊ฐ๋ ์ฐจ ์๋ ์ํ์์ ์๋ก์ด ์ฌ๋ฃ๋ฅผ ๋ถ๋๋ค. โ
- ๋น ๋ณด์ผ๋ฌ๋ฅผ ๋์ธ๋ค. โ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public class ChocolateBoiler {
private boolean empty;
private boolean boiled;
public ChocolateBoiler() {
empty = true;
boiled = false;
}
public void fill() {
if (isEmpty()) {
empty = false;
boiled = false;
}
}
public void boil() {
if (!isEmpty() && !isBoiled()) {
boiled = true;
}
}
public void drain() {
if (!isEmpty() && isBoiled()) {
empty = true;
}
}
public boolean isEmpty() {
return empty;
}
public boolean isBoiled() {
return boiled;
}
}
ํ์ง๋ง 2๊ฐ์ ChocolateBoiler ์ธ์คํด์ค๊ฐ ๋ฐ๋ก ๋์๊ฐ๋ฉด ์๋นํ ์ ์ข์ ์ํฉ์ด ์ผ์ด๋ ์ ์๋ค.\๋ง์ฝ ํ ์ ํ๋ฆฌ์ผ์ด์ ์์ ChocolateBoiler ์ธ์คํด์ค๊ฐ 2๊ฐ ์ด์ ๋ง๋ค์ด์ง๋ฉด ์ด๋ค ๋ฌธ์ ๊ฐ ์๊ธธ ์ ์์๊น?
๐ซย ์ฑ๊ธํด ํจํด์ ์ ์
์ฑ๊ธํด ํจํด(Singleton Pattern)์ ํด๋์ค ์ธ์คํด์ค๋ฅผ ํ๋๋ง ๋ง๋ค๊ณ , ๊ทธ ์ธ์คํด์ค๋ก์ ์ ์ญ ์ ๊ทผ์ ์ ๊ณตํ๋ค.
- ์ฑ๊ธํด ํจํด์ ์ค์ ๋ก ์ ์ฉํ ๋๋ ํด๋์ค์์ ํ๋๋ฟ์ธ ์ธ์คํด์ค๋ฅผ ๊ด๋ฆฌํ๋๋ก ๋ง๋ค๋ฉด ๋๋ค. ๊ทธ๋ฆฌ๊ณ ๋ค๋ฅธ ์ด๋ค ํด๋์ค์์๋ ์์ ์ ์ธ์คํด์ค๋ฅผ ์ถ๊ฐ๋ก ๋ง๋ค์ง ๋ชปํ๊ฒ ํด์ผ ํ๋ค. ์ธ์คํด์ค๊ฐ ํ์ํ๋ค๋ฉด ๋ฐ๋์ ํด๋์ค ์์ ์ ๊ฑฐ์น๋๋ก ํด์ผํ๋ค.
- ์ด๋์๋ ๊ทธ ์ธ์คํด์ค์ ์ ๊ทผํ ์ ์๋๋ก ์ ์ญ ์ ๊ทผ ์ง์ ์ ์ ๊ณตํ๋ค. ์ธ์ ๋ ์ด ์ธ์คํด์ค๊ฐ ํ์ํ๋ฉด ํด๋์ค์ ์์ฒญํ ์ ์๊ฒ ๋ง๋ค์ด ๋๊ณ , ์์ฒญ์ด ๋ค์ด์ค๋ฉด ๊ทธ ํ๋๋ฟ์ธ ์ธ์คํด์ค๋ฅผ ๊ฑด๋ค์ฃผ๋๋ก ๋ง๋ค์ด์ผ ํ๋ค.
๐น static uniqueInstance
- ์ฑ๊ธํด ๊ฐ์ฒด๋ฅผ ํด๋์ค ์์ค์์ ์ ์ฅํ๋ ์ ์ ๋ณ์
- ๋ฑ ํ๋์ ์ธ์คํด์ค๋ฅผ ์ ์ฅํด ๋์
๐น static getInstance()
- ์ฑ๊ธํด์ ํต์ฌ ๋ฉ์๋
- Singleton.getInstance()๋ผ๋ ์ฝ๋๋ง ์ฌ์ฉํ๋ฉด ์ธ์ ์ด๋์๋ ์ด ๋ฉ์๋๋ฅผ ํธ์ถํ ์ ์์
- ๊ฒ์ผ๋ฅธ ์ธ์คํด์ค๋ฅผ ์์ฑํ ์ ์๋ค๋ ์ฅ์ (= ํ์ํ ๋๊น์ง ๊ฐ์ฒด๋ฅผ ๋ง๋ค์ง ์๋๋ค)
๐ซย ์ด์ฝ๋ฆฟ ๋ณด์ผ๋ฌ์ ๋ฌธ์ ๋ฐ์
๊ณ ์ ์ ์ธ ์ฑ๊ธํด ํจํด์ผ๋ก ์ฝ๋๋ฅผ ๊ณ ์ณค์์๋ ChocolateBoiler์ ์๋ fill() ๋ฉ์๋์์ ์์ง ์ด์ฝ๋ฆฟ์ด ๋๊ณ ์๋๋ฐ ์๋ก์ด ์ฌ๋ฃ๋ฅผ ๋ฃ๊ณ ๋ง์๋ค. ๋ฉํฐ์ค๋ ๋๋ฅผ ์ฌ์ฉํ๋๋ก ์ด์ฝ๋ฆฟ ๋ณด์ผ๋ฌ ์ปจํธ๋กค๋ฌ๋ฅผ ์ต์ ํ์์ผฐ์ ๋ฟ์ธ๋ฐโฆ!
Step 1. Thread 1์ด getInstance()๋ฅผ ํธ์ถํจ
- uniqueInstance๊ฐ null์ธ์ง ํ์ธ โ true
- Thread 1์ ์ธ์คํด์ค๋ฅผ ์์ฑํ๋ ค๊ณ ํจ
Step 2. ๋์์ Thread 2๋ getInstance()๋ฅผ ํธ์ถํจ
- uniqueInstance๊ฐ ์ฌ์ ํ null (Thread A๊ฐ ์์ง ์์ฑ ์ ๋๋)
- Thread 2๋ ์ธ์คํด์ค ์์ฑ
๊ฒฐ๊ณผ: ์ธ์คํด์ค๊ฐ ๋ ๋ฒ ์์ฑ๋จ
- Thread 1 โ Singleton ์ธ์คํด์ค 1 ์์ฑ
- Thread 2 โ Singleton ์ธ์คํด์ค 2 ์์ฑ
์ ๋ฌธ์ ๋?
์ฑ๊ธํด์ ํ๋๋ง ์์ด์ผ ํ๋๋ฐ, ๋์์ ๋ง๋ค์ด์ ๋ ๊ฐ๊ฐ ๋์ด๋ฒ๋ฆฐ ๊ฑฐ
- ํ๋ก๊ทธ๋จ์ด ์ ์ญ์์ ๊ฐ์ ๊ฐ์ฒด๋ฅผ ๊ณต์ ํ ๊ฑฐ๋ผ๊ณ ๋ฏฟ๊ณ ์ฌ์ฉํ๋๋ฐ
- ์๊ณ ๋ณด๋ ๊ฐ์ ๋ค๋ฅธ ๊ฑธ ์ฐ๊ณ ์์ โ ๋ฒ๊ทธ ๋ฐ์ ๊ฐ๋ฅ
๐ซย ๋ฉํฐ์ค๋ ๋ฉ ๋ฌธ์ ํด๊ฒฐํ๊ธฐ
getInstance()๋ฅผ ๋๊ธฐํํ๋ฉด ๋ฉํฐ์ค๋ ๋ฉ๊ณผ ๊ด๋ จ๋ ๋ฌธ์ ๊ฐ ๊ฐ๋จํ๊ฒ ํด๊ฒฐ๋๋ค.
1
2
3
4
5
6
public static synchronized Singleton getInstance() {
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
synchronized ํค์๋๋ฅผ ์ถ๊ฐํ๊ฒ ๋๋ฉด ํ ์ค๋ ๋๊ฐ ๋ฉ์๋ ์ฌ์ฉ์ ๋๋ด๊ธฐ ์ ๊น์ง ๋ค๋ฅธ ์ค๋ ๋๋ ๊ธฐ๋ค๋ ค์ผ ํ๋ค. ์ฆ, 2๊ฐ์ ์ค๋ ๋๊ฐ ์ด ๋ฉ์๋๋ฅผ ๋์์ ์คํํ๋ ์ผ์ ์ผ์ด๋์ง ์๋๋ค.
์ด๋ฌ๋ฉด ๋ฌธ์ ๊ฐ ํด๊ฒฐ๋๊ธด ํ๊ฒ ์ง๋ง, ๋๊ธฐํํ ๋ ์๋ ๋ฌธ์ ๊ฐ ์๊ธฐ์ง ์๋์?
๋ง์.
๊ทธ๋ฆฌ๊ณ ์กฐ๊ธ ๋ ์๊ฐํด๋ณด๋ฉด ์ฌ์ค ๋๊ธฐํ๊ฐ ๊ผญ ํ์ํ ์์ ์ ์ด ๋ฉ์๋๊ฐ ์์๋๋ ๋๋ฟ์ด๋ผ๋ ์ฌ์ค์ ์ ์ ์๋ค. ๊ตณ์ด ์ด ๋ฉ์๋๋ฅผ ๋๊ธฐํ๋ ์ํ๋ก ์ ์งํ ํ์๊ฐ ์๋ค. ์ฆ, ์ฒ์์ ์ ์ธํ๋ฉด ๋๊ธฐํ๋ ๋ถํ์ํ ์ค๋ฒํค๋๋ง ์ฆ๊ฐ์ํฌ ๋ฟ์ด๋ค.
๐ซย ๋ ํจ์จ์ ์ผ๋ก ๋ฉํฐ์ค๋ ๋ฉ ๋ฌธ์ ํด๊ฒฐํ๊ธฐ
๋ฐฉ๋ฒ 1
getInstance()์ ์๋๊ฐ ๊ทธ๋ฆฌ ์ค์ํ์ง ์๋ค๋ฉด ๊ทธ๋ฅ ๋๋ค.
๋ฐฉ๋ฒ 2
์ธ์คํด์ค๊ฐ ํ์ํ ๋๋ ์์ฑํ์ง ๋ง๊ณ ์ฒ์๋ถํฐ ๋ง๋ญ๋๋ค.
์ ํ๋ฆฌ์ผ์ด์ ์์ Singleton์ ์ธ์คํด์ค๋ฅผ ์์ฑํ๊ณ ๊ณ์ ์ฌ์ฉํ๊ฑฐ๋ ์ธ์คํด์ค๋ฅผ ์คํ ์ค์ ์์๋ก ๋ง๋ค๊ณ ๊ด๋ฆฌํ๊ธฐ๊ฐ ์ฑ๊ฐ์๋ค๋ฉด ๋ค์๊ณผ ๊ฐ์ ๋ฐฉ๋ฒ์ ์ ์ฉํด ๋ณด์.
- ์ ์ ์ด๊ธฐํ ๋ถ๋ถ์์ Singleton์ ์ธ์คํด์ค๋ฅผ ์์ฑํ๋ค. ์ด๋ฌ๋ฉด ์ค๋ ๋๋ฅผ ์จ๋ ๋ณ ๋ฌธ์ ๊ฐ ์๋ค.
1
2
3
4
5
6
7
8
9
class Singleton {
private static instance: Singleton = new Singleton(); // ์ ์ด์ ๋ง๋ค์ด ๋์
private constructor() {}
public static getInstance(): Singleton {
return this.instance;
}
}
๋ฐฉ๋ฒ 3
โDCLโ์ ์จ์ getInstance()์์ ๋๊ธฐํ๋๋ ๋ถ๋ถ์ ์ค์ ๋๋ค.
Double-Checked Locking, DCL์ ์ฌ์ฉํ๋ฉด ์ธ์คํด์ค๊ฐ ์์ฑ๋์ด ์๋์ง ํ์ธํ ๋ค์ ์์ฑ๋์ด ์์ง ์์์ ๋๋ง ๋๊ธฐํํ ์ ์๋ค. ์ด๋ฌ๋ฉด ์ฒ์์๋ง ๋๊ธฐํํ๊ณ ๋์ค์๋ ๋๊ธฐํํ์ง ์์๋ ๋๋ค.
- volatile ํค์๋๋ฅผ ์ฌ์ฉํ๋ฉด ๋ฉํฐ์ค๋ ๋ฉ์ ์ฐ๋๋ผ๋ uniqueInstance ๋ณ์๊ฐ Singleton ์ธ์คํด์ค๋ก ์ด๊ธฐํ๋๋ ๊ณผ์ ์ด ์ฌ๋ฐ๋ฅด๊ฒ ์งํ๋๋ค.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Singleton {
private volatile static Singleton uniqueInstance;
private Singleton() {}
public static Singleton getInstance() {
// ์ธ์คํด์ค๊ฐ ์๋์ง ํ์ธํ๊ณ , ์์ผ๋ฉด ๋๊ธฐํ๋ ๋ธ๋ก์ผ๋ก ๋ค์ด๊ฐ
if (uniqueInstance == null) {
synchronized(Singleton.class) {
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
}
}
return uniqueInstance;
}
}
๐ซย ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ์ ์ ํ ๋ฐฉ๋ฒ ์ ํํ๊ธฐ
1. synchronized ๋ฐฉ์ (๋๊ธฐํ๋ ๋ฉ์๋)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
public class ChocolateBoiler {
private boolean empty;
private boolean boiled;
private static ChocolateBoiler uniqueInstance;
// ์์ฑ์๋ private โ ์ธ๋ถ์์ new ๋ชป ํ๊ฒ ๋ง์
private ChocolateBoiler() {
empty = true;
boiled = false;
}
// getInstance()์ synchronized ๋ถ์ฌ์ ์ค๋ ๋ ํ๋๋ง ์ ๊ทผ ๊ฐ๋ฅ
public static synchronized ChocolateBoiler getInstance() {
if (uniqueInstance == null) {
uniqueInstance = new ChocolateBoiler();
}
return uniqueInstance;
}
public void fill() {
if (isEmpty()) {
empty = false;
boiled = false;
}
}
public void boil() {
if (!isEmpty() && !isBoiled()) {
boiled = true;
}
}
public void drain() {
if (!isEmpty() && isBoiled()) {
empty = true;
}
}
public boolean isEmpty() {
return empty;
}
public boolean isBoiled() {
return boiled;
}
}
โ ์ฅ์
๋ฉํฐ์ค๋ ๋ ํ๊ฒฝ์์ ์์
์ฌ๋ฌ ์ค๋ ๋๊ฐ ๋์์ ์ ๊ทผํด๋ ๋จ ํ๋์ ์ธ์คํด์ค๋ง ์์ฑ
๊ตฌํ์ด ๋จ์
โ ๋จ์
- ๋งค๋ฒ ๋ฝ์ ๊ฑธ๊ธฐ ๋๋ฌธ์ ์ฑ๋ฅ ์ ํ๊ฐ ๋ฐ์ํ ์ ์์
- ํนํ ์ธ์คํด์ค๊ฐ ์ด๋ฏธ ๋ง๋ค์ด์ง ์ดํ์๋ getInstance()๋ฅผ ํธ์ถํ ๋๋ง๋ค ๋ฝ์ ๊ฑฐ๋ ๊ฑด ๋ญ๋น
2. ์ด๋ฅธ ์ด๊ธฐํ (Eager Initialization)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
public class ChocolateBoiler {
private boolean empty;
private boolean boiled;
// ์ธ์คํด์ค๋ฅผ ์ ์ด์ ๋ง๋ค์ด๋ฒ๋ฆผ (JVM ๋ก๋ฉ ์์ ์)
private static final ChocolateBoiler uniqueInstance = new ChocolateBoiler();
private ChocolateBoiler() {
empty = true;
boiled = false;
}
public static ChocolateBoiler getInstance() {
return uniqueInstance;
}
public void fill() {
if (isEmpty()) {
empty = false;
boiled = false;
}
}
public void boil() {
if (!isEmpty() && !isBoiled()) {
boiled = true;
}
}
public void drain() {
if (!isEmpty() && isBoiled()) {
empty = true;
}
}
public boolean isEmpty() {
return empty;
}
public boolean isBoiled() {
return boiled;
}
}
โ ์ฅ์
- ์ฝ๋๊ฐ ๊ฐ์ฅ ๊ฐ๋จํ๊ณ , ๋ฉํฐ์ค๋ ๋ ์์
- ํด๋์ค๊ฐ ๋ก๋ฉ๋ ๋ ์ธ์คํด์ค๊ฐ ๋ฑ ํ ๋ฒ ๋ง๋ค์ด์ง๊ณ ๋
- ์ดํ ์ ๊ทผ ์๋๊ฐ ๋น ๋ฅด๋ค. ๋ฝ์ด ํ์ X
โ ๋จ์
- ์ฐ๋ ์ ์ฐ๋ ๋ฌด์กฐ๊ฑด ์ธ์คํด์ค๋ฅผ ๋ง๋ค๊ธฐ ๋๋ฌธ์ ๋ฉ๋ชจ๋ฆฌ ๋ญ๋น ๊ฐ๋ฅ
- ์ธ์คํด์ค๋ฅผ ๋ง๋๋ ๋ฐ ์๊ฐ์ด ์ค๋ ๊ฑธ๋ฆฌ๋ ๊ฒฝ์ฐ, ์ฑ ๋ก๋ฉ ์ง์ฐ ๋ฐ์ ๊ฐ๋ฅ
3. Double-Checked Locking (์ด์ค ๊ฒ์ฌ ์ ๊ธ)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
public class ChocolateBoiler {
private boolean empty;
private boolean boiled;
// volatile: ์ค๋ ๋ ๊ฐ ๋ฉ๋ชจ๋ฆฌ ์ผ๊ด์ฑ ๋ณด์ฅ
private volatile static ChocolateBoiler uniqueInstance;
private ChocolateBoiler() {
empty = true;
boiled = false;
}
public static ChocolateBoiler getInstance() {
if (uniqueInstance == null) {
synchronized (ChocolateBoiler.class) {
if (uniqueInstance == null) {
uniqueInstance = new ChocolateBoiler();
}
}
}
return uniqueInstance;
}
public void fill() {
if (isEmpty()) {
empty = false;
boiled = false;
}
}
public void boil() {
if (!isEmpty() && !isBoiled()) {
boiled = true;
}
}
public void drain() {
if (!isEmpty() && isBoiled()) {
empty = true;
}
}
public boolean isEmpty() {
return empty;
}
public boolean isBoiled() {
return boiled;
}
}
โ ์ฅ์
- ์ต์ด ํ ๋ฒ๋ง ๋ฝ์ ๊ฑธ๊ธฐ ๋๋ฌธ์ ์ฑ๋ฅ์ด ์ข๋ค.
- ๋ฉํฐ์ค๋ ๋ ํ๊ฒฝ์์๋ ์์ ํ๊ณ , ์ด๋ฏธ ์ธ์คํด์ค๊ฐ ๋ง๋ค์ด์ก์ผ๋ฉด ๋ฝ ์์ด ๋น ๋ฅด๊ฒ ๋ฆฌํด๋จ
โ ๋จ์
- ๊ตฌํ์ด ๊ฐ์ฅ ๋ณต์กํ๋ค.
- ์ค์ํ๋ฉด ๋ฉํฐ์ค๋ ๋ ๋ฒ๊ทธ๊ฐ ์๊ธธ ์ ์์
- ์๋ฐ 1.4 ์ดํ์์๋ volatile ๋ฌธ์ ๋ก ์์ ํ ์์ ํ์ง ์์ (์์ฆ์ ๋๋ถ๋ถ ๊ด์ฐฎ)
โจ ์ธ์ ๋ญ ์จ์ผ ํ ๊น?
- ์ฑ๋ฅ๋ณด๋ค ๋จ์ํ ์ฝ๋๊ฐ ์ค์ํ๋ฉด โ
synchronized - ์ธ์คํด์ค๋ฅผ ๋ฌด์กฐ๊ฑด ์ธ ๊ฑฐ๊ณ ๋น ๋ฅธ ์๋๊ฐ ํ์ํ๋ฉด โ
eager - ์ ๋ง ํจ์จ์ด ์ค์ํ ๋ฉํฐ์ค๋ ๋ ํ๊ฒฝ์ด๋ฉด โ
DCL
๐ซย ๋ฐฉ๊ธ ๊นจ๋ฌ์๋๋ฐ์โฆ
enum์ ์ฌ์ฉํ๋ฉด ์ฑ๊ธํด์ ์ฌ๋ฌ ๋ฌธ์ ์ ์ ํด๊ฒฐํ ์ ์์ ๊ฒ ๊ฐ์์.
์ข์ ์๊ฐ์ ๋๋ค!
์ง๊ธ๊น์ง ์ฐ๋ฆฌ๊ฐ ํ๋ Singleton ํด๋์ค๋ฅผ ๋ง๋ค๊ณ ๋๊ธฐํํ๋ ์ผ์ ์ฑ๊ธํด์ด ์ด๋ป๊ฒ ์๋ํ๋์ง ํ์คํ ์ดํดํ๋ ค๊ณ ํ ๊ฒ์ด๊ณ , ์ฑ๊ธํด์ด ํ์ํ ๋๋ฉด ๋ฐ๋ก enum์ ์ฐ๋ฉด ๋๋ค.
๐ง ์ enum์ผ๋ก ์ฑ๊ธํด์ ๋ง๋ค๋ฉด ์ข์๊น?
์๋ฐ์์ enum์ ์ธ์ด ์ฐจ์์์ ๋จ ํ๋์ ์ธ์คํด์ค๋ง ์์ฑ๋๋๋ก ๋ณด์ฅํ๋ค. ์๋ฐ ์ปดํ์ผ๋ฌ์ JVM์ด ๋ด๋ถ์ ์ผ๋ก ๋ฉํฐ์ค๋ ๋ฉ ์์ ์ฑ๊น์ง ๋ณด์ฅํด ์ฃผ๊ธฐ ๋๋ฌธ์, ํนํ ๋ฉํฐ์ค๋ ๋ฉ + ์ง๋ ฌํ ๋ฌธ์ ๊น์ง ํ ๋ฒ์ ํด๊ฒฐํด์ผ ํ ๊ฒฝ์ฐenum ์ฑ๊ธํด์ ๋งค์ฐ ๊ฐ๋ ฅํ ์ ํ์ด๋ค!
1
2
3
4
5
6
7
8
9
10
public enum ChocolateBoiler {
INSTANCE; // ๋จ ํ๋์ ์ธ์คํด์ค (Singleton)
private boolean empty = true;
private boolean boiled = false;
public void fill() { ... }
public void boil() { ... }
public void drain() { ... }
}

