์ฐ๋ ๋ ์ธ์ดํํฐ(Thread Safety), ์ฌ๋ฌ ๊ฐ์ ์ฐ๋ ๋๊ฐ ๋์์ ์ด๋ค ๊ณต์ ์์(shared resource)์ ์ ๊ทผํ๋๋ผ๋ ํ๋ก๊ทธ๋จ์ด ์๋ชป๋ ๋์์ ํ์ง ์๋๋ก ๋ณด์ฅ๋๋ ์ํ๋ฅผ ์๋ฏธํฉ๋๋ค.
public class ObjectMapperHolder {
private static class SingletonHolder {
private static final ObjectMapper objectMapper = new ObjectMapper();
}
public static ObjectMapper getInstance() {
return SingletonHolder.objectMapper;
}
}
๋ผ์ด๋ธ๋ฌ๋ฆฌ ํ๋ก์ ํธ๋ฅผ ์งํํ๋ฉด์ ๋ณธํ๋ก์ ํธ์ ๋ ๋ฆฝ์ ์ผ๋ก ์ฌ์ฉํด์ผํ๋ ๊ธฐ๋ฅ(ObjectMapper, etc)๋ค์ด ์๊ฒจ๋์ ๋ฐ๋ก ์ฑ๊ธํค์ผ๋ก ๊ด๋ฆฌํ๊ธฐ๋ก ํ์ต๋๋ค.
๊ทธ๋ ๋ค๋ฉด ๋ชจ๋ ํด๋์ค๋ฅผ ์ฑ๊ธํคํจํด์ผ๋ก ๊ด๋ฆฌํด๋ ๋๋๊ฑธ๊น?
๋๋ค ๋น์ทํ ๋ง์ด๋ค, ๊ฒฐ๊ตญ์ ๋ด๋ถ๊ฐ์ด ๋ณ๊ฒฝ์ผ๋ก ์ธํด ์ฐ๋ ๋ ์ธ์ดํํฐ๊ฐ ๊นจ์ง๋ค๋ ๊ฒ์ด๋ค. ์๋ฅผ ๋ค์ด๋ณด์
public class UnsafeSingleton {
private static final UnsafeSingleton INSTANCE = new UnsafeSingleton();
private String status; // ์ํ๊ฐ!
private UnsafeSingleton() {}
public static UnsafeSingleton getInstance() {
return INSTANCE;
}
// getter, setter
}
UnsafeSingleton singleton = UnsafeSingleton.getInstance();
Thread t1 = new Thread(() -> singleton.setStatus("๊ณ ๊ธฐ ๋จน์"));
Thread t2 = new Thread(() -> singleton.setStatus("ํ๋ถ๊ธฐ ๋จน์"));
t1.start();
t2.start();
// ๊ฒฐ๊ณผ๊ฐ์???
System.out.println(singleton.getStatus());
์ด์ ๊ฐ์ ๊ฒฝ์ฐ, .getStatus() ๊ฐ ์ด๋ค ๊ฐ์ ๋ฐํํ ์ง๋ ์์ธกํ ์ ์์ต๋๋ค.
๊ทธ ์ด์ ๋.getStatus()์ ๋ฐํ๊ฐ์ Thread t1,t2 ์คํ์ด ์๋ฃ๋๋ ์์ ์ ๋ฐ๋ผ ๋ฌ๋ผ์ง๊ธฐ ๋๋ฌธ์ ๋๋ค.
Singleton์ ๋ชจ๋ ์ค๋ ๋๊ฐ ๋์ผํ ๊ฐ์ฒด ์ธ์คํด์ค๋ฅผ ๊ณต์ ํ๊ธฐ ๋๋ฌธ์, ์๋ํ์ง ์๊ฒ ์ํ๊ฐ์ด ๋ณ๊ฒฝ๋ ์ฌ์ง๊ฐ ์์ต๋๋ค.
์ฆ Singleton๋ณด๋ค๋ ๊ฐ๊ธฐ ๋ค๋ฅธ ๊ฐ์ฒด๋ก ๊ด๋ฆฌํ๋๊ฒ ์ ํฉํด ๋ณด์ ๋๋ค!
Singleton ํจํด์ด ์ ์ฉ๋ ํด๋์ค๋ ๋ด๋ถ ์ํ๊ฐ ์์ ์ ์ผ๋ก ์ ์ง๋์ด์ผ ํ๋ฉฐ, ๊ฐ์ด ์์ฃผ ๋ณ๊ฒฝ๋์ด์๋ ์ ๋ฉ๋๋ค. ์ด๋ฌํ ์์น์ ์ค๋ ๋ ์ธ์ดํํฐ(Thread Safety) ๋ฅผ ๋ณด์ฅํ๋ ๋ฐ ์ค์ํฉ๋๋ค.