...
It is safe to set shared class variables from the initialValue()
method. Consequently, each thread will see a consistent value of the flag
field.
Exceptions
Wiki Markup |
---|
*CON03:EX1*: The {{ObjectPreserver}} class (based on \[[Patterns 02|AA. Java References#Patterns 02]\]) is shown below: This class provides a mechanism for storing object references, which prevents an object from being garbage-collected, even if the remaining program no longer maintains a reference to the object. |
Code Block | ||
---|---|---|
| ||
import java.util.HashMap;
public class ObjectPreserver implements Runnable {
private static ObjectPreserver lifeLine = new ObjectPreserver();
private ObjectPreserver() {
Thread thread = new Thread( this);
thread.setDaemon( true);
thread.start(); // keep this object alive
}
// Neither this class, nor HashSet will be garbage collected.
// References from HashMap to other objects will also exhibit this property
private static final HashMap<Integer,Object> protectedMap = new HashMap<Integer,Object>();
public synchronized void run(){
try {
wait();
} catch(InterruptedException e) { /* Forward to handler */ }
}
// Objects passed to this method will be preserved until
// the unpreserveObject method is called
public static void preserveObject(Object obj) {
protectedMap.put(0, obj);
}
// Returns the same instance every time
public static Object getObject() {
return protectedMap.get(0);
}
// Unprotect the objects so that they can be garbage collected
public static void unpreserveObject() {
protectedMap.remove(0);
}
}
|
This is a singleton class (see CON23-J. Address the shortcomings of the Singleton design pattern for how to properly handle singleton classes). The initialization creates a background thread referencing the object, and the thread itself waits forever. Consequently this object exists for the remainder of the JVM's lifetime; however, as it is managed by a daemon thread, the thread (and object) will not hinder a normal shutdown of the JVM.
While the initialization does involve a background thread, the background thread accesses no fields and so creates no deadlock. Consequently this code is a safe and useful exception to this rule.
Risk Assessment
Starting and using background threads during class initialization can result in deadlock conditions.
...
Wiki Markup |
---|
\[[Bloch 05b|AA. Java References#Bloch 05b]\] 8. "Lazy Initialization"
\[[Patterns 02|AA. Java References#Patterns 02]\] Chapter 5, Creational Patterns, Singleton |
...
CON02-J. Always synchronize on the appropriate object 11. Concurrency (CON) CON04-J. Use the private lock object idiom instead of the Class object's intrinsic locking mechanism