The singleton pattern is a common design pattern in Java, and it is also a question I often ask in interviews.

According to my preliminary statistics, about 60% of people can name 2-4 singleton implementations, about 40% can name 5-6 singleton implementations, and only about 20% can name 7 singleton implementations.

Less than 1% could name more than seven singleton implementations.

In fact, as an interviewer, THE reason I ask about singleton mode most of the time is because it can ask a lot of questions.

Such knowledge as thread safety, class loading mechanism, principle of synchronized, principle of volatile, instruction rearrangement and memory barrier, implementation of enumeration, reflection and singleton pattern, how serialization breaks singleton, CAS, ABA problem of CAS, Threadlocal and so on.

In general, I only need to start with a single example, and I can probably complete the whole process of an interview. I can ask all the things I want to ask, and I can have a comprehensive understanding of the level of an interviewer.

Here is a snapshot of an interview scene, starting with the singleton mode:

Q: Do you know how to implement a thread-safe singleton without using synchronized and lock?

A: I know. It can be implemented using “static inner classes”.

Static inner classes implement the singleton pattern:

public class Singleton {      private static class SingletonHolder {      private static final Singleton INSTANCE = new Singleton();      }      private Singleton (){}      public static final Singleton getInstance() {      returnSingletonHolder.INSTANCE; }}Copy the code

Q: Are there other ways to do this besides static inner classes?

A: And there are two hungrier models.

Elehan implements singleton mode:

public class Singleton {      private static Singleton instance = new Singleton();      private Singleton (){}      public static Singleton getInstance() {      returninstance; }}Copy the code

Hanhan variant realizes singleton pattern:

public class Singleton {      private Singleton instance = null;      static {      instance = new Singleton();      }      private Singleton (){}      public static Singleton getInstance() {      returnthis.instance; }}Copy the code

Q: Are all the ones you mentioned above thread-safe?

A: It is thread-safe

Q: How is thread-safe?

A: Is it because I used static and the class load is thread-safe?

Q: Actually, synchronized is not entirely correct. It is used indirectly, though not directly.

(There are two different directions depending on the answer: 1. Classloading mechanism, modularity, etc. 2, continue to ask the singleton pattern)

Thread-safety guarantees during class loading

The above static inner class, hunhaner, etc., all define static member variables to ensure that the singleton can be instantiated during class initialization.

This takes advantage of the thread-safety mechanism of the ClassLoader. The loadClass method of the ClassLoader uses the synchronized keyword when loading classes.

So, unless overridden, this method is thread-safe by default throughout the load process. So object creation during class loading is also thread-safe.

Q: Back to the original question, do you know how to implement a thread-safe singleton without using synchronized and lock?

(This is not intended to be a hot pursuit, but rather to provoke more thought.)

A: Well, enumerations can also implement singletons.

Enumeration implements the singleton pattern:

public enum Singleton {      INSTANCE;      public void whateverMethod() {}}Copy the code

Q: Do you know how enumerating singletons work? How do you keep threads safe?

Enumerate thread-safety issues for singletons

Enumerations are implemented by relying on the Enum class, whose member variables are static and instantiated in a static block of code, much like hungry, so they are naturally thread-safe.

Q: So enumerations actually use synchronized. Do you know of a way to avoid using synchronized altogether?

A: en… I think

Q: do you know CAS? Can singletons be implemented using CAS?

(During the interview, if the interviewer is familiar with locks, I will most likely continue to ask questions in two directions: 1. 2, non-lock, such as CAS, ThreadLocal, etc.)

A: Oh, I know that CAS is an optimistic locking technique. When multiple threads try to update A variable using CAS at the same time, only one of them succeeds.

Realize singleton mode with CAS (AtomicReference) :

public class Singleton {    private static final AtomicReference<Singleton> INSTANCE = new AtomicReference<Singleton>();
    private Singleton() {}
    public static Singleton getInstance() {        for (;;) {            Singleton singleton = INSTANCE.get();            if(null ! = singleton) {return singleton;            }
            singleton = new Singleton();            if (INSTANCE.compareAndSet(null, singleton)) {                returnsingleton; }}}}Copy the code

Q: What are the advantages and disadvantages of singletons implemented using CAS?

A: The advantage of CAS is that there is no need to use the traditional locking mechanism to ensure thread safety. CAS is an algorithm based on busy waiting, which depends on the implementation of the underlying hardware. Compared with locking, it has no additional consumption of thread switching and blocking, and can support A larger degree of parallelism.

Q: You seem to be talking about strengths? What about the weaknesses?

Disadvantages of CAS implementation singletons

A major disadvantage of CAS is that it can cause significant execution overhead on the CPU if the busy wait is never executed successfully (in an infinite loop).

Singleton = new singleton (); “, a large number of objects will be created, which may cause memory overflow.

Q: Well, besides CAS, do you know of any other ways to implement singletons without synchronized?

A: I really don’t know this time.

Q :(let me remind him again) consider ThreadLocal and see if it can be implemented?

(I almost always remind interviewees when they are running out of ideas, and then move on to another question.)

A: ThreadLocal? Is that ok?

Q: What do you understand about ThreadLocal

(Through his answer, it seems that he has some doubts about this idea and doesn’t worry. Start with a simple question to give the interviewer a sense of confidence, and then move on.)

ThreadLoacal

ThreadLocal provides a separate copy of variables for each thread, isolating conflicting data access from multiple threads. For the problem of multi-threaded resource sharing, synchronized adopts the “time-for-space” approach, while ThreadLocal adopts the “space-for-time” approach.

Whereas synchronization provides only one copy of a variable that different threads queue to access, ThreadLocal provides one copy of a variable for each thread, so it can be accessed simultaneously without affecting each other.

Q: Is it theoretically possible to implement singletons using ThreadLocal?

A: That should work, too.

Using ThreadLocal to implement the singleton pattern:

public class Singleton {     private static final ThreadLocal<Singleton> singleton =     new ThreadLocal<Singleton>() {         @Override         protected Singleton initialValue() {            returnnew Singleton(); }}; public static SingletongetInstance() {        return singleton.get();     }          private Singleton() {}}Copy the code

Q: Uh-huh. Ok, that’s enough about the implementation of the singleton pattern.

(The term ThreadLocal is mainly used to test candidates’ understanding of ThreadLocal and whether they can apply the knowledge to different situations. In fact, the so-called “singleton” has lost the meaning of singleton.)

(But to be honest, very few people can answer this question, and most interviewees basically lose their train of thought on the first few questions, and most of the time they don’t even ask the question and move on.)

A :(secretly pleased) yeah, I’ve learned A lot. Thank you

Q: so… Do you know how to break singletons?

A singleton question, a must-ask. To serialization and reflection)

A :(um….)