Java ----- Singleton design pattern on

Example 1. Single-mode writing DCL

Singleton design pattern, there is a double check wording lock, so-called lazy formula

class Single{
  private static Single sSingle;

  private Single() {}

  public static Single getInstance() {
    if(sSingle == null) {
      synchronized(Single.class) {
        if(sSingle == null) {
          sSingle = new Single();
        }
      }
    }
    return sSingle;
  }

}

2.DCL wording of the question

Such an approach, if the code detecting means using sonar, warning will specifically be described below

Double-checked locking is the practice of checking a lazy-initialized object's state both before and after a synchronized block is entered to determine whether or not to initialize the object.

It does not work reliably in a platform-independent manner without additional synchronization for mutable instances of anything other than float or int. Using double-checked locking for the lazy initialization of any other type of primitive or mutable object risks a second thread using an uninitialized or partially initialized member while the first thread is still creating it, and crashing the program.

There are multiple ways to fix this. The simplest one is to simply not use double checked locking at all, and synchronize the whole method instead. With early versions of the JVM, synchronizing the whole method was generally advised against for performance reasons. But synchronized performance has improved a lot in newer JVMs, so this is now a preferred solution. If you prefer to avoid using synchronized altogether, you can use an inner static class to hold the reference instead. Inner static classes are guaranteed to load lazily.                        

Probably mean

Use double-checked locking could result in a second thread to use an uninitialized member or part of the initialization, and the first thread is still created it, and the program crashes.

There are several ways to solve this problem. The easiest way is to not use double-checked locking, but the entire synchronization method. For earlier versions of the JVM, for performance reasons, usually not recommended to synchronize the entire method.

However, newer jvm, the synchronization performance has been greatly improved, so now it is a preferred solution. If you want to avoid using synchronized, you can use the internal static class to hold a reference. Internal static class can be guaranteed lazy loading.

So writing a single case of DCL is not recommended

 

In the "Java Concurrency in Practice" for in such an approach, there is such a description

Find some information, there are generally described this problem, simple terms:

A thread is assumed to perform sSingle = new Single () statement appears to be one where the code, but in fact it is not an atomic operation, this code will eventually be compiled into a plurality of assembler instructions, which generally do three things

(1) Single allocate memory for the Examples;

(2) call to Single () constructor to initialize member fields;

(3) A pointer to the allocated memory sSingle the object space (sSingle case was not null)

However, due to the Java compiler allows out of order execution, and JDK1.5 before the JMM Cache, register to main memory write-back of provisions of the order, the order (2) and (3) above is not guaranteed. In other words, the order may be 1-2-3, 1-3-2 may be.

If the latter, and is finished in (3), (2) not previously done, the thread is switched to B, for which time has been executed because sSingle a third point in the thread A, sSingle has a non-null state, thread B direct value sSingle, an error occurs when re-use,

This is the DCL failures, and this is difficult to track errors that are difficult to reproduce may be hidden for a long time

                                                      ----- Excerpt from "Android source code analysis and practical design patterns"

After JDK1.5, SUN officials have noticed this problem, adjust the volatile keyword, if after JDK1.5 version, simply change the wording

class Single{
  // 此处加上volatile   
private volatile static Single sSingle;   private Single() {}   public static Single getInstance() {     if(sSingle == null) {       synchronized(Single.class) {         if(sSingle == null) {           sSingle = new Single();         }       }     }     return sSingle;   } }

On the volatile keyword, how much it will affect some performance, but for the correctness of the program, the performance of this sacrifice is worth it

 

3. Singleton design pattern recommended wording

For Singleton design pattern, below the recommended wording

public class Single {

    private Single() {
    }

    public static Single getSingle() {
        return SingleHolder.holder;
    }

    private static class SingleHolder {
        private static final Single holder = new Single();
    }
}

 

4. Appendix

1. With regard to the principle of DCL failures aspect, this article describes in more detail, it is recommended to look at

  Java Concurrency --- DCL failures  

 

2. With regard to JMM, volatile keyword, this article is very detailed

  java concurrent programming: volatile keyword analysis

 

Guess you like

Origin www.cnblogs.com/sweep/p/12243387.html