...
This compliant solution declares the Helper
object as volatile
and consequently uses the correct form double-check locking idiom.
Code Block | ||
---|---|---|
| ||
// Works with acquire/release semantics for volatile // Broken under JDK 1.4 and earlier class Foo { private volatile Helper helper = null; public Helper getHelper() { if (helper == null) { synchronized(this) { if (helper == null) { helper = new Helper(); // If the helper is null, create a new instance } } } return helper; // If helper is non-null, return its instance } } |
Wiki Markup |
---|
JDK 5.0 allows a write of a {{volatile}} variable to be reordered with respect to a previous read or write. A read of a {{volatile}} variable cannot be reordered with respect to any following read or write. Because of this, the double checked locking idiom can work when {{helper}} is declared {{volatile}}. If a thread initializes the {{Helper}} object, a happens-before relationship is established between this thread and another that retrieves and returns the instance. \[[Pugh 04|AA. Java References#Pugh 04]\] and \[[Manson 04|AA. Java References#Manson 04]\] |
Wiki Markup |
---|
"Today, the double-check idiom is the technique of choice for lazily initializing an instance field. While you can apply the double-check idiom to {{static}} fields as well, there is no reason to do so: the lazy initialization holder class idiom is a better choice." \[[Bloch 08|AA. Java References#Bloch 08]\]. |
Compliant Solution (immutable
)
...
Code Block | ||
---|---|---|
| ||
public class Helper {
private final int n;
public Helper(int n) {
this.n = n;
}
// other fields & methods, all fields are final
}
class Foo {
private Helper helper = null;
public Helper getHelper() {
if (helper == null) {
synchronized(this) {
if (helper == null) {
helper = new Helper(); // If the helper is null, create a new instance
}
}
}
return helper; // If helper is non-null, return its instance
}
}
|
...
Variables declared static
are guaranteed to be initialized and made visible to other threads immediately. Static initializers also exhibit these properties. This approach should not be confused with eager initialization because in this case, the Java Language Specification guarantees lazy initialization of the class when it will be first used.
Compliant Solution (
...
initialize-on-demand holder class idiom)
This compliant solution explicitly incorporates lazy initialization. It also uses a static
variable as suggested in the previous compliant solution. The variable is declared within a static
inner, Holder
class.
...
Wiki Markup |
---|
This idiom is called the initialize-on-demand holder class idiom. Initialization of the {{Holder}} class is deferred until the {{getInstance()}} method is called, following which the {{helper}} is initialized. The only limitation of this method is that it works only for {{static}} fields and not instance fields. \[[Bloch 01|AA. Java References#Bloch 01]\]. This idiom is a better choice than the double checked locking idiom for lazily initializing {{static}} fields \[[Bloch 08|AA. Java References#Bloch 08]\]. |
Exceptions
EX1: Explicitly synchronized code (that uses method synchronization or proper block synchronization, that is, enclosing all initialization statements) does not require the use of double-checked locking.
...