I encountered such a problem when performing PMD static code detection on the project
Partially created objects can be returned by the Double Checked Locking pattern when used in Java. An optimizing JRE may assign a reference to the baz variable before it calls the constructor of the object the reference points to.
Note: With Java 5, you can make Double checked locking work, if you declare the variable to be volatile.
It is possible that when using double-checked lock mode, an incompletely initialized object will be returned. Some people may doubt the concept of partially initialized objects, please continue to analyze
<code>public static Singleton getSingleton() {<br> if (instance == null) { <br> synchronized (Singleton.class) {<br> if (instance == null) { <br> instance = new Singleton();<br> }<br> }<br> }<br> return instance ;<br>}</code>
We see that both inside and outside the synchronized code block are judged instance == null, this is because multiple threads may enter the if judgment outside the synchronized code block at the same time. If the null judgment is not performed inside the synchronized code block, multiple instances may be initialized.
This way of writing seems to be perfect, but it is problematic, or it does not guarantee that it will be perfect. The main reason is that instance = new Singleton(); is not an atomic operation.
Creating an object can be divided into three parts:
<code>1.分配对象的内存空间<br>2.初始化对象<br>3.设置instance指向刚分配的内存地址<br>当instance指向分配地址时,instance是不为null的</code>
However, between steps 2 and 3, it may be reordered, causing the order of creating objects to become 1-3-2. Imagine a scenario:
Thread A creates the object Singleton for the first time, and the object creation order is 1-3-2;
After allocating memory to the instance, a thread B comes and calls the getSingleton() method
This When the instance == null judgment is made, it is found that the instance is not null.
But note that instance has not initialized the object at this time, and thread B will return the uninitialized object. Problems may occur when thread B uses instance. This is the problem of double-check lock.
For the above problems, we can solve the above problem by declaring instance as volatile
<code>public class Singleton{<br> private volatile static Singleton instance;<br> public static Singleton getSingleton() {<br> if (instance == null) { <br> synchronized (Singleton.class) {<br> if (instance == null) { <br> instance = new Singleton();<br> }<br> }<br> }<br> return instance ;<br> }<br>}</code>
But it must be used in JDK5 version or above.
<code>public class Singleton { <br> private static class SingletonHolder { <br> private static final Singleton INSTANCE = new Singleton(); <br> } <br> private Singleton (){} <br> public static final Singleton getInstance() { <br> return SingletonHolder.INSTANCE; <br> } <br>}</code>
The currently recommended way of writing is to use static inner classes, which can achieve lazy loading without thread safety issues. And it reduces the overhead of synchronized.
The above is the detailed content of What is java double check lock mode. For more information, please follow other related articles on the PHP Chinese website!