One of the ways to achieve thread safety when creating instance variables is to make a use of ThreadLocal class. When instance variable is wrapped in ThreadLocal, each thread accessing the variable has its own independent copy of the variable.
An even better approach is to wrap the instance variable in SoftReference, which can eliminate the risk if getting OutOfMemoryError if there is a need to keep a an object in memory for a long period of time, for example when implementing caching mechanism. The garbage collector will only collect softly referenced objects when it decides that memory is low enough to warrant it
Consider the following snippet:
[java]
public class ThreadSafeExample {
private static final ThreadLocal<SoftReference<List<SomeObject>>> trhLocal =
new ThreadLocal<SoftReference<List<SomeObject>>>();
.
.
public static List<SomeObject> getSafeList() {
// Get the value of the current thread’s copy of this thread-local variable
SoftReference<List<SomeObject>> reference = trhLocal.get();
if (reference != null) {
// Get this reference object’s referent
List<SomeObject> safeList = reference.get();
if (safeList != null) {
return safeList;
}
}
// Ok, so we did not have previously anything,
// lets create thread-local variable
List<SomeObject> safeList = new LinkedList<SomeObject>();
reference = new SoftReference<List<SomeObject>>(safeList);
trhLocal.set(reference);
return safeList;
}
}
[/java]
What happens in the above example is, when getSafeList() is called, the thread’s list is assigned the first time it invokes getSafeList(), which causes invocation of trhLocal.get(). If get() does not return anything, a new copy of the instance variable is created and set to the ThreadLocal instance. Each thread holds an implicit reference to its copy of a thread-local variable as long as the thread is alive and the ThreadLocal instance is accessible. This approach does not require synchronization, which can create thread contention, and provides much faster access to the variable than via synchronization.
Off course one should consider whether ThreadLocal is really needed. Normally, a good candidates for object re-use via thread local are objects that are frequently accessed by a given thread and are non-trivial to construct. Another scenario for making use of ThreadLocal, would be when it is not really practical to extend Thread class (for example creating servlets) and thread safety is needed.