Singleton mode double check volatile and double null

  The first is the code, the classic double lock writing.

public class Singleton {
    
    
    private volatile static Singleton Instance;
    private Singleton(){
    
    }
    public static Singleton getInstance(){
    
    
        if(Instance == null){
    
    
            synchronized(Singleton.class){
    
    
                if(Instance == null){
    
    
                    Instance = new Singleton()}
            }
        }
        return Instance;
    }
}

  Let me talk about the reasons why it is necessary to judge twice. The first judgment is to verify whether to create an object, to avoid locking each thread during multi-threaded access, and to improve efficiency. The second judgment is to avoid repeated creation of singletons, because it may There will be multiple threads that pass the first judgment and are waiting for the lock to create a new instance object.

  For example: there are three threads, when A and B call getSingleton at the same time, it is judged that the first if is empty. At this time, A gets the lock and performs the second level if judgment. The condition is established and an object is new; because of Synchronized reason, B is outside The layer waits, A is created, the lock is released, B gets the lock, and the second layer if judgment is performed. The condition is not established, and the lock is released. When C calls getSingleton, the first level of judgment is not established, and the singleton object is returned directly to avoid entering the lock and reduce performance overhead.

  Talking about why there is Synchronized but still need volatile to modify Instance. The volatile modified variable is only to prohibit instruction reordering, because when Instance = new Singleton(); creates an object, the bottom layer will be divided into four instruction executions: (the following is the correct order of instruction execution)
①, if the class has not been loaded, Then load the class
②, open up memory space adr in the heap, used to store the created object
③, execute the construction method to instantiate the object
④, assign the memory address adr opened in the heap to the volatile modified Instance reference variable

  If the Instance reference variable is not modified with volatile, it may be that the compiler and the processor have reordered the instructions, causing step ④ to be executed before step ③. At this time, the Instance reference variable is not null, but the Instance reference The object in the memory address in the heap pointed to by the variable has not been instantiated, and the instance object is still null; then it is not null when it is first judged to be null, and then it will report NPE null pointer exception when it is used. Up.

Guess you like

Origin blog.csdn.net/hou_ge/article/details/111166954