1. Preface
About the design pattern of the article has been not written, because the total feeling to turn over the book, just use code to do what Cat,dog class, and then a eat method,abstract a animal to knock over the code is too boring, no practical application, or deep thinking, It's a waste of time to stick the code over the books. The reason for writing this article today is that there are some interesting and meaningful things to think about, so let's start.
2. Consideration of single case
In general, the initialization of a single case is divided into two types according to the timing of loading, a hungry man and lazy, among which the lazy type is divided into static inner class and double lock.
This time, we are divided according to the principle of thread safety in concurrent scenarios, based on the class loading mechanism and based on the double locking mechanism.
2.1 Based on class loading mechanism
First, the A Hungry man type,
public class Foo { private static final Foo INSTANCE=new Foo(); public static getInstance(){ return foo; }}
Then there is the static inner class in the lazy type. Because the class is loaded the first time it is used, deferred loading is possible.
public class Singleton { public static getInstance(){ return Inner.INSTANCE; } private static final Inner{ static final Singleton INSTANCE=new Singleton(); }}
Both are thread-safe because the class is initialized only once, and the static constant field is initialized only once, in Java's class-loading mechanism.
How does the JVM guarantee that classes will only be loaded once? Take a look at ClassLoader's LoadClass method fragment:
protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException{ synchronized (getClassLoadingLock(name)) { // First, check if the class has already been loaded Class c = findLoadedClass(name);
Notice that the display uses a synchronized
keyword to get the load lock, so this is why class loading is thread-safe.
2.2 Double locking mechanism
Code:
public class Singleton { private volatile static Instance INSTANCE; public static Instance getInstance() { if (INSTANCE == null) { synchronized (Singleton.class) { if (INSTANCE == null) INSTANCE = new Instance(); } } return INSTANCE; }}
Because synchronized
of the performance overhead, this double locking mechanism has been invented to perfectly implement lazy loading. If the first check instance is not NULL, then you do not need to perform the following locking and initialization operations.
Note that the static constant field of a double-lock implementation class uses a keyword: volatile
this is necessary in a concurrency scenario.
At the time of executing the statement INSTANCE = new Instance();
, the JVM hierarchy can be considered to have done so three operations
memory = allocate(); //1:分配对象的内存空间ctorInstance(memory); //2:初始化对象instance = memory; //3:设置instance指向刚分配的内存地址
But for the JVM to optimize performance, there is an optimization operation called order reordering. The above instructions may be optimized to
memory = allocate(); //1:分配对象的内存空间instance = memory; //3:设置instance指向刚分配的内存地址 //注意,此时对象还没有被初始化!ctorInstance(memory); //2:初始化对象
That is, the instance object may not be initialized when the thread reads to instance is not NULL if a reorder occurs. Using an uninitialized object is likely to cause an exception.
volatile
when it comes to keyword action, one of them is to prevent the JVM from ordering reordering of commands in concurrent scenarios.
This is the complete resolution of the double lock mechanism implementation.
Conclusion
Although this is only the simplest model in the design pattern, but in-depth discovery can extend to the class loading, synchronized,volatile and other Java principles of thinking, at first it was not thought, indeed some interesting things. More details on this principle are recommended in the following articles.
Double check locking and deferred initialization
Deep understanding of the Java Memory Model series articles
Chulung
Original link: https://chulung.com/article/62
This article was automatically synced to Cnblogs by Metaclblog on 2016-12-05 09:00:00
False
Design Pattern 1: Thinking of the principle of single case mode