Explain how to write singleton pattern correctly in Java

Single case mode is the easiest to understand and handwritten code mode in design mode, but it involves a lot of knowledge points, so it is often used as an interview question. Generally, single examples are written in five ways: lazy, hungry, double check lock, static internal class and enumeration. In order to record the learning process, several common single example writing methods are sorted out here,

Bronze 5: (lazy loaded, but thread unsafe)

When asked to implement a singleton pattern, many people's first reaction is to write the following code, including that taught us in textbooks.

This code is simple and clear, and uses delayed loading mode, but the thread is not safe. When the getInstance () method is called in a multithreaded environment, multiple threads may enter the program code block of the if statement.

Lazy: synchronized (lazy loaded, thread safe, but not efficient)

To solve the above problem, the simplest way is to set the entire getInstance () method to synchronized.

Although it achieves thread safety and delayed loading, it is not efficient. Because only one thread can call the getInstance () method at any time. However, the synchronized operation only needs to be called the first time, that is, when the singleton instance object is created for the first time. This mode causes that even after the singleton is created, only one thread can access the getInstance () method at a time, which will lead to potential performance problems. This leads to double check locks.

Hungry Han style: static final field (non lazy loaded)

This method is very simple, because the instance of a singleton is declared as static final and will be initialized when the class is loaded into memory for the first time, so creating an instance object is thread safe (guaranteed by the JVM Implementation).

It is not a lazy loading mode. Instance will be initialized at the beginning after loading the class, even if the client does not call the getInstance () method. This will lead to some usage restrictions: for example, the creation of singleton instance depends on parameters or configuration files. Before getInstance (), you must call a method to set parameters to it, so this singleton writing method cannot be used. Similar methods include:

Double check lock + volatile (lazload, thread safe, but obscure)

Double check lock mode (double checked locking pattern) is a method of locking with synchronization block. Programmers call it double checked lock because instance = = null is checked twice, one outside the synchronization block and the other inside the synchronization block. Why do you need to check again in the synchronization block? Because multiple threads may enter if outside the synchronization block together. If it is in the synchronization block Multiple instance objects will be generated without secondary verification.

This code looks perfect, but unfortunately it has a problem. It mainly lies in the sentence instance = new singleton(), which is not an atomic operation. In fact, this sentence does the following three things in the JVM.

However, there is an optimization of instruction reordering in the JIT compiler of the JVM. In other words, the sequence of the second and third steps above cannot be guaranteed, and the final execution sequence may be 1-2-3 or 1-3-2. If it is the latter, it will be preempted by thread 2 before 3 is executed and 2 is not executed. At this time, instance is already non null (but not initialized), so thread 2 will directly return instance, use it, and then report an error naturally. Therefore, we need to declare the instance variable as volatile.

However, special attention should be paid to the problem of using volatile double check lock in versions before Java 1.5. This problem can only be fixed in Java 1.5, so you can rest assured to use volatile after that.

Static internal class: IODH, initialization on demand holder

This pattern combines the knowledge of Java's static internal classes and multi-threaded default synchronization locks, and skillfully realizes delayed loading and thread safety at the same time.

The static inner class is equivalent to the static part of its outer class. Its object does not depend on the outer class object, so it can be created directly. Static inner classes are reproduced only when they are first used.

Multithreaded default synchronization lock

As we all know, in multithreading development, in order to solve the concurrency problem, we mainly use synchronized to add mutex for synchronization control. However, in some cases, the JVM has implicitly performed synchronization for you, which eliminates the need for manual synchronization control. These include:

1. When data is initialized by static initializers (initializers on static fields or static {} blocks)

 2. When accessing the final field

 3. When creating an object before creating a thread

 4. When a thread can see the object it is going to process

Enum enum

From Java 1.5, you only need to write an enumeration type containing a single element:

This method is similar to the public domain method in function, but it is more concise. It provides a serialization mechanism for free and absolutely prevents multiple instantiations, even when facing complex serialization or reflection attacks. Although this method has not been widely used, the enumeration type of single element and become the best method to implement singleton.

--------------------Here are some implementation methods with doubtful details---------------------

1. What are the details of static final

2. Does the assignment initialization at static field have priority over static code block?

3. How to write the singleton mode of static internal class

4. Does the example in P50 in Java EE design pattern parsing and application really have a lazload effect?

The above is the whole content of this article. I hope the content of this article can bring some help to your study or work. At the same time, I also hope to support a lot of programming tips!

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>