C
Cephalobus_alienus
Shalloway and Trott, in their book Design Patterns
Explained, 2nd edition, published what they claim to
be a fix for the broken Double-Checked Locking Pattern.
Would the following truly be a valid means of
implementing a thread-safe singleton?
--- Begin quote from Design Patterns Explained ---
When the Double-Checked Locking pattern was converted
from C++ to Java, it was soon discovered that it did
not work for Java.[4] The reason is that the Java
compiler, in its optimization efforts, may return the
reference to an object from a constructor before the
constructor is through instantiating the object. Thus,
dosync may complete before USTax is actually completely
built. This may cause a problem. Also an optimizing
compiler may "notice" that there is "no way" for the
"instance" member to change state between the two "if"
statements, and optimize the second one out. You can
avoid this problem in C# by using the keyword volatile.
[4] See the book's Web site at http://www.netobjectives.com/dpexplained
for more information on this.
A Solution for Java
It is not all that hard to fix this-not that I figured
it out on my own. One solution is to take advantage of
the class loader, as shown in Example 21-4.
Example 21-4. Java Code Fragment: Instantiation Only
public class USTax extends Tax {
private static class Instance {
static final Tax instance= new USTax();
}
private static USTax instance;
private USTax() { }
public static Tax getInstance() {
return Instance.instance;
}
}
This works because the inner class (Instance) will get
loaded only once; therefore, only one USTax object is
built.
--- End quote from Design Patterns Explained ---
Thanks for your comments,
Jerry
Explained, 2nd edition, published what they claim to
be a fix for the broken Double-Checked Locking Pattern.
Would the following truly be a valid means of
implementing a thread-safe singleton?
--- Begin quote from Design Patterns Explained ---
When the Double-Checked Locking pattern was converted
from C++ to Java, it was soon discovered that it did
not work for Java.[4] The reason is that the Java
compiler, in its optimization efforts, may return the
reference to an object from a constructor before the
constructor is through instantiating the object. Thus,
dosync may complete before USTax is actually completely
built. This may cause a problem. Also an optimizing
compiler may "notice" that there is "no way" for the
"instance" member to change state between the two "if"
statements, and optimize the second one out. You can
avoid this problem in C# by using the keyword volatile.
[4] See the book's Web site at http://www.netobjectives.com/dpexplained
for more information on this.
A Solution for Java
It is not all that hard to fix this-not that I figured
it out on my own. One solution is to take advantage of
the class loader, as shown in Example 21-4.
Example 21-4. Java Code Fragment: Instantiation Only
public class USTax extends Tax {
private static class Instance {
static final Tax instance= new USTax();
}
private static USTax instance;
private USTax() { }
public static Tax getInstance() {
return Instance.instance;
}
}
This works because the inner class (Instance) will get
loaded only once; therefore, only one USTax object is
built.
--- End quote from Design Patterns Explained ---
Thanks for your comments,
Jerry