싱글턴 패턴은 객체가 단 하나만 필요할 때 사용하는 패턴이다.

스레드 풀, 캐시, 로그 저장용 객체 등 과 같은 상황에서 사용할 수 있다.

싱글턴 패턴을 구현하는 방법은 다음과 같다.

public class Singleton {

	private static Singleton uniqueInstance;

	// Private 생성자. 이 클래스 안에서만 호출할 수 있다.
	private Singleton() {}
	
	// 객체를 얻는 메서드. Singletom.getInstance() 와 같이 사용한다.
	public static Singleton getInstance() {
		// 객체를 담고 있는 변수가 Null일 때 객체를 생성한다.
		if (uniqueInstance == null) {
			uniqueInstance = new Singleton();
		}
		// 저장된 객체 반환
		return uniqueInstance;
	}
}

이 코드는 객체를 실제로 사용할 때 생성하기 때문에, Lazy instantiation 이라고 부른다.

하지만 위 코드는 스레드 안전하지 않다.

여러 스레드가 동시에 getInstance()를 호출하게 되면, new Singleton() 이 여러번 실행되어 객체가 여러개 생길 수 있다.

이 부분은 synchronized 키워드를 추가하면 해결이 가능하다.

public class Singleton {

	private static Singleton uniqueInstance;

	private Singleton() {}
	
	// synchronized를 사용하여 메서드에 진입할 때 스레드 동기화
	public static synchronized Singleton getInstance() {
		if (uniqueInstance == null) {
			uniqueInstance = new Singleton();
		}
		return uniqueInstance;
	}
}

이 코드도 완벽하지는 않다.

getInstance()를 호출할 때마다 synchronized 키워드로 인해 lock이 걸리기 때문에 오버헤드가 심하다는 단점이 있다.

스레드 동기화 오버헤드를 없애기 위해서는 다음과 같은 방법을 사용해 볼 수 있다.

추가로 이펙티브 자바에서는 변수가 하나인 열거형(Enum)을 사용하는 것도 싱글턴을 구현하는 좋은 방법이라고 소개하고 있다.