This is the 25th day of my participation in the August Challenge

This is a continuation of the article “Challenging the singleton pattern (I)”, which discussed the hunger-style singleton implementation method, and this article discusses the lazy singleton implementation method.

Slacker style

Lazy singletons are instantiated before they are used, and the object is instantiated only when the method that gets the instance is called, such as getInstance, creating the instance in the global access method.

The implementation is as follows:

public class SingletonInLazy { private SingletonInLazy(){ } public static SingletonInLazy INSTANCE = null; public static SingletonInLazy getInstance(){ if(INSTANCE == null){ INSTANCE = new SingletonInLazy(); } return INSTANCE; }}Copy the code

The instantiation of the class occurs in the provided public static method getInstance. Running in a single-threaded environment is any problem, but in a multi-threaded environment multiple objects are instantiated. Let’s write a test case that opens up two new threads to execute the getInstance method.

  static final Runnable RUNNABLE = ()->{
        final SingletonInLazy instance = SingletonInLazy.getInstance();
        System.out.println(Thread.currentThread().getName()+ ":" + instance);
    };
​
    public static void main(String[] args) {
        final Thread thread1 = new Thread(RUNNABLE);
        final Thread thread2 = new Thread(RUNNABLE);
        thread1.start();
        thread2.start();
        System.out.println("end");
​
    }
Copy the code

The running results are as follows:

The result is fairly obvious: two instance objects are indeed generated. However, this is not always the case, and sometimes only one object is produced, so lazy singletons are potentially thread-safe.

Tip, if you want to debug code in multithreaded mode, you can use the Idea tool for debugging in thread mode, manually control the execution order to track the changing state of memory.

Since threads are not safe, we can make them thread-safe by locking them, for example by adding the synchronized keyword to the getInstance static method.

 public synchronized static SingletonInAnotherHungry getInstance(){
        return INSTANCE;
    }
Copy the code

In multi-threaded environment, the getInstance method is called, and there are no more objects. The problem of thread safety is solved. However, using the method of locking, when the number of threads opened is relatively large, ·】synchronized upgrades to heavyweight lock, and threads that do not obtain lock resources will be blocked, resulting in unnecessary consumption of resources and a significant decline in the running performance of the program. So is there a better way? The answer, of course, is to use double-checked locks.


Didn’t see enough, please jump to the next article design pattern | challenge singleton pattern (3)