3 implementations of the singleton pattern

1. Instantiate when the singleton class is loaded. This implementation is called the hungry Chinese pattern.

 1 public class Singleton {
 2     private static Singleton instance;
 3     
 4     static {
 5         instance = new Singleton();
 6     }
 7 
 8     private Singleton() {
 9     }
10 
11     public static Singleton getInstance() {
12         return instance;
13     }
14 }

2. Instantiate when the singleton object is used for the first time. This implementation is called the lazy mode.

 1 public class Singleton {
 2     private static Singleton instance;
 3     
 4     private Singleton() {
 5     }
 6     
 7     public static Singleton getInstance() {
 8         if (instance == null) {
 9             instance = new Singleton();
10         }
11         
12         return instance;
13     }
14 }

      Note that this implementation is thread-unsafe . Assuming that before the singleton class is instantiated, there are two threads acquiring the singleton object at the same time. After thread 1 executes line 8 if (instance == null), the thread scheduling mechanism allocates CPU resources to thread 2. This When thread 2 executes line 8 if (instance == null), it also finds that the singleton class has not been instantiated, which will cause the singleton class to be instantiated twice. To prevent this from happening, the getInstance() method needs to be synchronized. Let's take a look at the improved lazy mode:

 1 public class Singleton {
 2     private static Singleton instance;
 3     
 4     private Singleton() {
 5     }
 6     
 7     // 线程安全的懒汉模式
 8     public synchronized static Singleton getInstance() {
 9         if (instance == null) {
10             instance = new Singleton();
11         }
12         
13         return instance;
14     }
15 }

3. Double check

      In the second implementation, each time a singleton object is acquired, a lock will be added, which will result in performance loss. The implementation of double locking is essentially a lazy mode, which will have a greater performance improvement than the second implementation.

 1 public class Singleton {
 2     private volatile static Singleton instance;
 3     
 4     private Singleton() {
 5     }
 6     
 7     public static Singleton getInstance() {
 8         if (instance == null) {
 9             synchronized (Singleton.class) {
10                 if (instance == null) {
11                     instance = new Singleton();
12                 }
13             }
14         }
15         
16         return instance;
17     }
18 }

       Even if multiple threads pass the judgment of if (instance == null) in line 8 at the same time when the singleton class is instantiated, only one thread enters the synchronization area after acquiring the lock at the same time. Since each thread judged by line 8 will obtain the lock and enter the synchronization area in turn, after entering the synchronization area, it is necessary to judge again whether the singleton class has been instantiated by other threads to avoid multiple instantiations. Since the double locking implementation only needs to lock when instantiating the singleton class, it will bring about a performance improvement compared to the second implementation. Another thing to note is that double locking requires adding the volatile modifier to the instance field. Since synchronized does not lock the instance instance (because there is no instance yet), after the thread modifies the value of the instance after executing line 11, it should immediately write the modified instance to the main memory (main memory), and It is not temporarily stored in registers or high-speed buffers (caches) to ensure that new values ​​are visible to other threads.

      Supplement: Line 9 can lock any object. To enter the synchronization area, the lock of this object must be obtained. Since you don't know the purpose of other objects' locks, the best way here is to lock Singleton.class.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325332430&siteId=291194637