Do you really understand the java singleton pattern? Talk about details that others have overlooked!

Foreword: Lao Liu dare to make a guarantee in this article that the singleton mode of java speaks better than most technical blogs, and tells details that other technical blogs do not have! ! !

1 java singleton mode

Directly talk about the two methods to realize the singleton mode: lazy man and hungry man. The concept of singleton mode can be searched online by myself, so I won't talk about it here!

This will involve the jvm in java. If you don't have knowledge in this area, I suggest you to make up for it first, otherwise you will be a little confused!

First of all, when is the class loaded?

The java virtual machine does not have mandatory constraints, but for initialization, it strictly stipulates that there are only four cases where the class must be initialized first.

What we need to know is that in the process of class loading, loading, verification, and preparation are completed before initialization, so after initialization, loading, verification, and preparation are naturally completed before.

Then in these four situations, when the four instructions of new, getstatic, putstatic, and invokestatic are encountered, if the corresponding class is not initialized, the corresponding class must be initialized first.

After talking about the timing of class loading, you can talk about the lazy man and the hungry man.

Let me just talk about why the lazy man is thread-unsafe?

Look at the first code:

public class Student2 {
    
    

    //1:构造私有
    private Student2(){
    
    }
    //2:定义私有静态成员变量,先不初始化
    private static Student2 student = null;

    //3:定义公开静态方法,获取本身对象
    public static Student2 getSingletonInstance(){
    
    
        //没有对象,再去创建
        if (student == null) {
    
    
            student = new Student2();
        }
        //有对象就返回已有对象
        return student;
    }   
}

Combined with the content of class loading mentioned earlier, class loading will be performed when new or static method is loaded.

Thread 1 new an object, thread 2 also new an object immediately, the value of the second object overwrites the value of the first object, no matter how many objects are new, garbage objects will be generated, only the last object Only when it is kept, other objects will become unreachable objects and be garbage collected. This process is equivalent to producing a large number of invalid objects. This is the reason for thread insecurity!

So what should we do to make the lazy man thread safe?

Look at the code:

public class Student4 {
    
    

    private volatile static Student4 student = null;
    private Student4() {
    
    }

    public static Student4 getSingletonInstance() {
    
    
        if (student == null) {
    
    //第一个null判断,是先大范围过滤一遍
            synchronized (Student4.class) {
    
    
                if (student == null) {
    
    
                    student = new Student4();
                }
            }
        }
        return student;
    }
}

This is called double check lock DCL. The first if first determines whether it is null or not. After synchronization, thread 1 is executed first, and then thread 2 can enter. Then the second if determines whether the creation of the class instance is completed, thread After 1 is created, thread 2 does not need to be created.

Then why add the volatile keyword?

Because the execution process of our Student student = new Student() is:

1. New triggers the class loading mechanism (classes that have been loaded do not need to be loaded again)

2. Allocate memory space

3. The object is initialized. 4. The object reference address is assigned to the variable in the stack space. However, the JIT instant editor in our JVM will optimize the code execution process and change the process to 1, 2, 4, and 3.

What does it mean? It is directly assigned without initialization, so that the student has a value directly, but the entire object has not been initialized yet, so this object is incomplete and an unfinished product. In the JVM specification, it is an object that cannot be used at all.

At this time, thread 1 has done so many things. We let it take a break and stop the CPU for a while. Thread 2 will come and it will get the object directly, but it will report an error when it calls the method of the object. Although this object has a value, it has not been initialized yet. So we have to add the volatile keyword to prohibit instruction reordering.

The interview in the hardest hit area is almost done, and the hungry man still has to talk about it.

Finally, let's talk about why there is no thread safety issue in Hungry Chinese Style?

Look at the code:

public class Student1 {
    
    
    // 2:成员变量初始化本身对象
    private static Student1 student = new Student1();
    // 构造私有
    private Student1() {
    
    
    }
    // 3:对外提供公共方法获取对象
    public static Student1 getSingletonInstance() {
    
    
        return student;
    }
    public void sayHello(String name) {
    
    
        System.out.println("hello," + name);
    }
}

According to what the class loads, under multi-threaded conditions, when thread 1 executes getSingletonInstance() first, the class will be loaded and the static resources of the class will be initialized. According to the JVM security mechanism, when a class is loaded by the JVM, the loading of the class is thread-safe, which is equivalent to the JVM locking the process.

So the whole process is in the scope of a lock, and then the static member variable is initialized, which is equivalent to Student1() being new, and it will only be new once.

When the second thread comes in, it finds that the class has already been loaded, and there is no need to load it, and the object does not need to be created frequently, so the thread is safe!

2 summary

Lao Liu has read a lot of information about the java singleton mode, more or less there will be a lack of details, this time Lao Liu has completed it.

Finally, if you feel that there is something wrong or wrong, you can contact the official account: Lao Liu who works hard to communicate.

If you think the writing is good, give Lao Liu a thumbs up!

Guess you like

Origin blog.csdn.net/qq_36780184/article/details/111598392
Recommended