
본 글 이외에 다양하게 싱글톤을 만드는 방법은 존재합니다. 아래의 글은 본인이 공부하면서 필요하다고 생각되는 부분만 적었습니다.
싱글톤 패턴은 클래스의 인스턴스 객체가 메모리상에 딱 하나만 존재하도록 하는 패턴이다.
public class SingletonObject {
private static final SingletonObject singletonObject = new SingletonObject();
private SingletonObject() {
}
public static SingletonObject getInstance() {
return singletonObject;
}
}
public class SingletonObject2 {
private static SingletonObject2 singleObject2 = null;
private SingletonObject2() {
}
public static SingletonObject2 getInstance() {
if (singleObject2 == null) {
singleObject2 = new SingletonObject2();
}
return singleObject2;
}
}
위의 구현 방식은 Thread-Safe 하지 않다.
package thread.singleton;
import java.util.ArrayList;
import java.util.List;
public class SingletonTest {
public static void main(String[] args) {
List<Thread> threadPool = new ArrayList<>();
for (int i = 0; i < 1000; i++) {
threadPool.add(new Thread(() -> {
try {
System.out.println(Thread.currentThread().getName() + " : " + SingletonObject2.getInstance().hashCode());
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}));
}
for (int i = 0; i < threadPool.size(); i++) {
threadPool.get(i).start();
}
}
}
1000개의 쓰레드가 동시에 getInstance() 를 호출했을 때 같은 객체를 바라봐야하지만 결과는 그렇지 않았다.

getInstance() 메서드가 호출됨.singleObject2 변수가 null이므로 if 문의 조건을 만족하여 객체 생성을 시도.new SingletonObject2()를 통해 객체를 생성하고 singleObject2 변수에 할당.getInstance() 메서드가 호출됨.singleObject2 변수가 null이 아님을 확인하고 if 문의 조건을 통과하지 못하므로 객체를 생성하지 않고 기존 객체를 반환하려 함.singleObject2 변수에 할당했으므로, 기존 객체를 반환하는 대신 새로운 객체를 다시 생성하고 singleObject2 변수에 할당.공유자원에 서로 다른 스레드가 접근하려고 할 때 문제가 생기고 있음.
이를 해결하기 위해 상호 배제 사용, 그 중에서 자바에서는 synchronized 키워드를 제공함. 대표적인 monitor 기법
public static synchronized SingletonObject2 getInstance() throws InterruptedException {
if (singleObject2 == null) {
singleObject2 = new SingletonObject2();
}
return singleObject2;
}
private static volatile SingletonObject2 instance;
public static SingletonObject2 getInstance() throws InterruptedException {
if (instance == null) {
synchronized(SingletonObject2.class){
if (instance == null) {
instance = new SingletonObject2();
}
}
}
return singleObject2;
}
Double Checked Locking : 잠금을 획득하기 전에 잠금 기준("잠금 힌트")을 테스트하여 잠금 획득의 오버헤드를 줄이는 데 사용되는 소프트웨어 디자인 패턴