A thread-safe Singleton guarantees only one instance of a class is ever created even when multiple threads request it concurrently. In Java, the most common efficient approach is the initialization-on-demand holder idiom, which relies on class-loading guarantees instead of explicit synchronization.
Key Points: • The JVM guarantees a class is initialized exactly once, and only when it's first referenced, which the holder idiom exploits. • The Singleton instance lives inside a private static inner class that isn't loaded until getInstance() is called. • No synchronized keyword is needed, so there's no ongoing locking overhead after initialization. • Alternatives include an eager static final field, double-checked locking with a volatile field, or an enum-based Singleton. • Enum Singletons are the simplest fully safe option since Java also protects them against reflection and serialization attacks.
Example: A ConfigurationManager that reads settings from disk once and shares them across the application is a good Singleton candidate, since re-reading configuration per thread would be wasteful and could cause inconsistent state.
Code Example:
public class ConfigurationManager {
private ConfigurationManager() {
// load configuration
}
private static class Holder {
private static final ConfigurationManager INSTANCE = new ConfigurationManager();
}
public static ConfigurationManager getInstance() {
return Holder.INSTANCE;
}
}Interview Tip: A concise interview answer is:
"I implement thread-safe Singletons with the initialization-on-demand holder idiom: a private static inner class holds the instance, and the JVM's class-loading guarantees make it lazy and thread-safe without any explicit synchronization. For very simple cases I'd just use an enum, since it's inherently safe against reflection and serialization."