How to use double check lock to implement singleton - ImportNew in Java

This paper is composed of ImportNew-freely flowing style of writing Translation from javacodegeeks . Welcome to join Java team . Please refer to the requirements at the end of the article for reprint.

Singleton classes are very common in Java developers, but they pose many challenges to junior developers. One of the key challenges they face is how to ensure that the behavior of a singleton class is singleton? That is, how to prevent a singleton class from having multiple instances for any reason. In the whole application life cycle, to ensure that only one instance of a single class is created, Double checked locking of Singleton is an implementation method. As the name implies, in a double check lock, the code checks twice Singleton class Whether there are existing instances. Lock one time and do not lock one time to ensure that no more than one instance will be created. By the way, in JDK 1.5, Java fixed problems with its memory model. Before JDK 1.5, there was a problem with this approach. In this article, we will see how to use java to implement the singleton class of double check lock, why there is a problem with double check lock before Java 5, and how to solve this problem. By the way, this is also an important interview point. I was interviewed in financial and service companies and was asked to implement the single case mode of double check lock by hand. Trust me, this is very difficult unless you clearly understand what you are doing. You can also read my complete list“ Single case pattern design ”To better prepare for the interview.

Why do you need double check locks to implement singleton classes?

A common scenario in which a singleton class violates a contract in a multithreaded environment. If you want a novice to write Singleton mode , you may get the following code:

    private static Singleton _instance;

    public static Singleton getInstance() {
        if (_instance == null) {
            _instance = new Singleton();
        }
        return _instance;
    }

Then, when you point out that this code will create multiple instances when more than one thread is called in parallel, it is likely to set the entire getInstance() method to synchronous( synchronized ), as shown in the second example code getinstances () method. Although it is thread safe and solves the problem of multiple instances, it is not efficient. When you call this method, you need to bear the performance overhead brought by synchronization. However, synchronization is only needed when you first call it, that is, when a singleton class instance is created. This will enable us to use double checked locking pattern, a method of locking code only in critical area. Programmers call it a double check lock because there are two checks_ instance == null, one is unlocked, the other is locked on the synchronization block. This is an example of using Java double check locks:

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


This method looks perfect on the surface. You only need to pay the cost of synchronization block once, but it still has problems. Unless you declare_ instance variable volatile keyword. Without the volatile modifier, another thread in Java might see a half initialized_ instance, but after using the volatile variable, you can ensure that the relationships occur first. For volatile variables_ instance, all write s will occur in read first, which is not the case before Java 5, so there is a problem with using double check lock before that. Now, with happens before guarantee, you can safely assume that it will work well. In addition, this is not the best way to create a thread safe singleton mode. You can use the Enumeration implementation of singleton mode , which provides built-in thread safety at instance creation time. Another method is to use static holder pattern.

    /*
     * A journey to write double checked locking of Singleton class in Java.
     */

    class Singleton {

        private volatile static Singleton _instance;

        private Singleton() {
            // preventing Singleton object instantiation from outside
        }

        /*
         * 1st version: creates multiple instance if two thread access
         * this method simultaneously
         */

        public static Singleton getInstance() {
            if (_instance == null) {
                _instance = new Singleton();
            }
            return _instance;
        }

       /*
        * 2nd version : this definitely thread-safe and only
        * creates one instance of Singleton on concurrent environment
        * but unnecessarily expensive due to cost of synchronization
        * at every call.
        */

       public static synchronized Singleton getInstanceTS() {
           if (_instance == null) {
               _instance = new Singleton();
           }
           return _instance;
       }

       /*
        * 3rd version : An implementation of double checked locking of Singleton.
        * Intention is to minimize cost of synchronization and  improve performance,
        * by only locking critical section of code, the code which creates instance of Singleton class.
        * By the way this is still broken, if we don't make _instance volatile, as another thread can
        * see a half initialized instance of Singleton.
        */

        public static Singleton getInstanceDC() {
            if (_instance == null) {
                synchronized (Singleton.class) {
                    if (_instance == null) {
                        _instance = new Singleton();
                    }
                }
            }
            return _instance;
        }
    }

That's all of this article. This is a Creating thread safe singleton mode with Java Using enumeration to implement singleton class is more simple and effective. I don't recommend that you implement singleton patterns like this, because there are many better ways to use Java. However, this problem has historical significance, and also teaches how concurrency introduces some subtle mistakes. As mentioned before, this is a very important point in the interview. Before you go to any Java interview, practice implementing a singleton class with a handwritten double check lock. This will enhance your insight into the coding mistakes that Java programmers make. In addition, in today's Test Driven Development In, singleton mode is regarded as anti pattern because it is difficult to simulate its behavior, so if you are a test driven development developer, it is better to avoid using singleton mode.

Original link: javacodegeeks Translation: ImportNew.com-freely flowing style of writing
Translation link: http://www.importnew.com/12196.html
[for reprint, please keep the original source, translator and translation link. ]

Tags: Programming Java JDK

Posted on Mon, 01 Jun 2020 10:01:25 -0400 by will_1990