The double check pattern is mentioned in Article 48 of the book Effective Java, and it is pointed out that this pattern is not usually applicable in Java. The structure of this pattern is as follows:
public Resource getResource() { if (resource == null) { synchronized(this){ if (resource==null) { resource = new Resource(); } } } return resource; }This pattern is an improvement to the following code:
public synchronized Resource getResource(){ if (resource == null){ resource = new Resource(); } return resource; }The purpose of this code is to delay initialization of resource. But every time you access it, you need to synchronize. In order to reduce the overhead of synchronization, a double check mode is available.
The reason why the double check mode is invalid in Java is that the reference type is not thread-safe in the absence of synchronization. For basic types except long and double, double, double check mode is applicable. For example, the following code is correct:
private int count; public int getCount(){ if (count == 0){ synchronized(this){ if (count == 0){ count = computeCount(); //A time-consuming calculation} } } return count; }The above is the general conclusion about the double-check idiom in Java. But things are not over yet, because Java's memory pattern is also being improved. Doug Lea wrote in his article: "According to the latest JSR133 Java memory model, if the reference type is declared as volatile, the double check mode will work." So in the future, you need to use the double check mode in Java, you can use the following code:
private volatile Resource resource; public Resource getResource(){ if (resource == null){ synchronized(this){ if (resource==null){ resource = new Resource(); } } } return resource; }Of course, it must be in Java that follows the JSR133 specification.
Therefore, double-check is not available in J2SE 1.4 or earlier versions due to out-of-order writes when tuning in multi-threaded or JVM. This problem has been fixed in J2SE 5.0, and the volatile keyword can be used to ensure singletons under multi-threading.
public class Singleton { private volatile Singleton instance = null; public Singleton getInstance() { if (instance == null) { synchronized(this) { if (instance == null) { instance = new Singleton(); } } return instance; } }The recommended method is Initialization on Demand Holder (IODH).
public class Singleton { static class SingletonHolder { static Singleton instance = new Singleton(); } public static Singleton getInstance(){ return SingletonHolder.instance; } }The above is all about this article, I hope it will be helpful for everyone to learn Java programming.