Implement singleton mode

How to implement singleton mode

Title: design a class, we can only generate an instance of this class.

What is singleton mode?

Some introductions of the singleton mode are not repeated here. For more information, please refer to the following blog posts:
https://www.cnblogs.com/xuwendong/p/9633985.html
Or read the book "Dahua design patterns"

Implementation mode

  1. Hungry man (thread safe)
    What is hungry Han style?
    The hungry man is to initialize the singleton once the class is loaded, so as to ensure that the singleton already exists when getInstance.

Disadvantages: the class is loaded into memory when it is created, and it will always occupy memory even if it is not applicable.
Advantage: it will also be faster on the first call because its resources have been initialized.

public class Singleton{
	private static Singleton singleton = new Singleton ();
	private Singleton (){
	}

	public static Singleton getInstance(){
		return singleton ;
	}
}
  1. Lazy (thread unsafe)
    What is lazy?
    This means that the singleton is initialized only when it is used.

    Disadvantages: the object will only be instantiated when the singleton is used for the first time. Initialization is required when calling for the first time. If there is a lot of work to be done, there will be some delay in performance.
    Advantages: do not call getInstance method and do not occupy memory space.

public class Singleton{
	private static Singleton singleon;

	private Singleton (){
	}
	public static Singleton getInstance(){
		if(singleton==null){
			singleon = new Singleton();
		}
		return singleton ;
	}
}
  1. Lazy (thread safe)
    Although it is a thread safe method, it is too inefficient.
    When multiple threads want to create an instance at the same time, they will compete for locks. Only the thread that obtains the lock can execute. Other threads enter the blocking queue and wait for the lock to be released.
public class Singleton{
	private static Singleton singleon;

	private Singleton (){
	}
	public static synchronized Singleton getInstance(){
		if(singleton==null){
			singleon = new Singleton();
		}
		return singleton ;
	}
}
  1. Double check lock (DCL) (thread safe & lazy)
    Compared with the above method, there is one more judgment. When the instance is created, there will be no lock contention, and the efficiency has been greatly improved. However, there is a low probability of thread insecurity (the instance object is not initialized).

This is due to the reordering of instructions in the case of multithreading. You can see the details in 3.8.2 of the art of Java Concurrent Programming.
In general, I can create an object in three steps
1. Allocate address space for objects
2. Initialization object
3. Set the reference to the memory address.

2 and 3 here may be reordered, and then the current thread A executes in the order 1, 3 and 2 at this time. When the thread executes to 3, although it points to the memory address, the object has not been initialized. Suppose that thread A runs out of A time slice and gives up the CPU, and thread B obtains the right to use the CPU. At this time, it is judged that the instance is not empty and the uninitialized memory address is returned, which leads to A thread safety problem.

public class Singleton{
	//If volatile is not added, thread safety problems may occur.
	private static volatile Singleton singleon;

	private Singleton (){
	}
	public static Singleton getInstance(){
		if(singleton==null){
			synchronized(Singleton.class){
				if(singleton==null){
					singleon = new Singleton();
				}
			}
		return singleton ;
	}
}
  1. Static inner class (thread safe & lazy)
    Using the static inner class code is simple and can achieve the lazy effect, because the static inner class will not be loaded and the Singleton instance will not be created until the getInstance() method is called.
public class Singleton{
	private static class InnerSingletonHolder{
		private static Singleton inner = new Singleton();
	}

	private Singleton (){
	}
	public static Singleton getInstance(){
		return InnerSingletonHolder.inner;
	}
}
  1. Enumeration (thread safe)
    Effective Java is the way advocated by the author. The code is very simple, but it is not suitable for scenarios that need inheritance.
enum Singleton{
    INSTANCE;
    public void otherMethod(){
    }
}

Summary: the above are the implementation methods of singleton mode I summarized. The recommended implementation methods here are static internal classes and enumeration.
For lazy thread safety, you can contact the synchronized keyword, the underlying principle, lock optimization and so on.
For the way of static internal classes, you can contact the class loading mechanism of the JVM.
For DCL, you can write it out during the interview and then talk about volatile.

Tags: Java

Posted by robwilson on Sat, 14 May 2022 13:12:42 +0300