How to correctly write the singleton mode and the correct writing mode

Source: Internet
Author: User

How to correctly write the singleton mode and the correct writing mode

The Singleton mode is the easiest to understand in the design mode and the easiest to write code. However, there are a lot of knowledge points involved in it, so it is often used as an interview question. In general, there are five ways to write a single statement: lazy, hungry, dual-validation lock, static internal class, and enumeration. In order to record the learning process, several common Singleton statements are compiled here,

Bronze 5 :( Lazy-loaded, but thread is not secure)

When asked about how to implement a singleton model, many people first wrote the following code, including textbooks, which taught us this way.

public class Singleton {    private static Singleton instance;    private Singleton(){}    public static Singleton getInstance() {     if (instance == null) {         instance = new Singleton();     }     return instance;    }}

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

Lazy: synchronized (Lazy-loaded, thread security, but not efficient)

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

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

Although thread security and delayed loading are achieved, it is not efficient. At any time, only one thread can call the getInstance () method. However, the synchronized operation is only required for the first call, that is, when you create a single instance object for the first time. This mode causes potential performance problems even after a single instance is created, there is only one thread to access the getInstance () method at a time. This leads to a double check lock.

Hungry Chinese: static final field (non-Lazy-loaded)

This method is very simple, because the instance of a single instance is declared as static final and will be initialized when the class is loaded into the memory for the first time, therefore, creating instance objects is thread-safe (implemented by JVM ).

Public class Singleton {// class initialization when loading private static final Singleton instance = new Singleton (); private Singleton () {} public static Singleton getInstance () {// Singleton with static factory return instance ;}}

It is not a lazy loading mode. The instance will be initialized at the beginning after the class is loaded, even if the client does not call the getInstance () method. This causes some restrictions: for example, if a Singleton instance is created based on parameters or a configuration file, you must call a method to set parameters before getInstance, in this way, the singleton writing method cannot be used. Similar methods include:

Public class Singleton {public static final Singleton instance = new Singleton (); // Singleton with public final field private Singleton () {}}// <valid Java> the difference between the two is described on page 1.
Double check lock + volatile (Lazyload, thread security, but obscure)

Double checked locking pattern is a method that uses synchronous block locking. The programmer calls it a double check lock because there will be two checksinstance == null, Once out of the synchronization block, once in the synchronization block. Why do I need to test the synchronization block again? Because there may be multiple threads entering the if outside the synchronization block together, if there is no secondary check in the synchronization block, multiple instance objects will be generated.

public static Singleton getSingleton() {    if (instance == null) {                         //Single Checked        synchronized (Singleton.class) {            if (instance == null) {                 //Double Checked                instance = new Singleton();            }        }    }    return instance ;}

This code looks perfect, but unfortunately it is faulty. Mainly lies ininstance = new Singleton()This sentence is not an atomic operation. In fact, the following three things are done in JVM.

However, optimization of Command Re-sorting exists in the JIT compiler of JVM. That is to say, the order of the second and third steps is not guaranteed. The final execution order may be 1-2-3 or 1-3-2. If it is the latter, it will be preempted by thread 2 before 3 is finished and 2 is not executed. At this time, the instance is not null (but it is not initialized ), therefore, thread 2 will directly return the instance and then use it. Then, an error is automatically reported. Therefore, we need to declare the instance variable as volatile.

Public class Singleton {private volatile static Singleton instance; // declare it as volatile private Singleton () {} public static Singleton getSingleton () {if (instance = null) {synchronized (Singleton. class) {if (instance = null) {instance = new Singleton () ;}} return instance ;}}

However, I pay special attention to the problem that the volatile double check lock was used in Java 1.5 or earlier versions. This problem was fixed only in Java 1.5, so I can safely use volatile after that.

Static internal class: IoDH, Initialization-on-demand holder 

This mode combines the knowledge of Java's static internal classes and multi-thread default synchronization locks, and cleverly implements delayed loading and thread security at the same time.

public class Singleton {    private Singleton() {}    private static class LazyHolder {        private static final Singleton INSTANCE = new Singleton();    }    public static Singleton getInstance() {           // From wikipedia        return LazyHolder.INSTANCE;    }}

A static internal class is equivalent to the static part of its external class. Its objects do not depend on external class objects, so they can be directly created. Static internal classes are reprinted only when they are used for the first time.

Default synchronization lock for multiple threads

As we all know, in multi-thread development, to solve the concurrency problem, we mainly use synchronized to apply mutex lock for synchronization control. However, in some cases, the JVM has implicitly performed synchronization for you. In such cases, manual synchronization control is not required. These situations include:

1. When data is initialized by the static initiator (on the static field or in the static {} block)

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 Enumeration

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

public enum Singleton {    INSTANCE;}

This method is similar to the public domain method in function, but it is more concise and provides a serialization mechanism free of charge, which absolutely prevents multiple instantiation, even in the case of complex serialization or reflection attacks. Although this method has not been widely used, the enumeration type of a single element and it has become the best way to implement Singleton.

 

-------------------- The following are some of the implementation methods with doubts ---------------------

1. What are the details of static final?

2. Is there a sequence between the value assignment initialization at static field and the static code block?

3. How to Write the singleton mode of static internal classes?

4. Does the Lazyload effect apply to parsing the P50 in Java EE design patterns?

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.