Tuesday, February 8, 2011

Thread-Safe Singleton Using ThreadLocal

Let's say a given component in your application has these constraints:

  1. it needs a reference to an object that is expensive to construct
  2. the expensive object state can be set just once, i.e. it never changes
  3. it executes in a multi-threaded context
  4. maximum throughput is required

Constraint #1 seems to call for an instance variable - i.e. you don't want to use a method-local field since the object construction is expensive, as such you don't want to do it each time the object is needed. Constraint #2 implies that a singleton will serve our needs. However, constraint #3 means the singleton must be used in a thread-safe manner - and constraint #4 tells us that we want to avoid synchronization if possible.

Overall, these constraints are similar to the forces that brought the double-checked locking pattern into play some years ago - however, as we subsequently learned, that pattern is broken and is considered an anti-pattern. Don't use it.

There are many suitable alternatives - here's one that uses ThreadLocal to address all four constraints:

  1. declare a static final ThreadLocal with an initialization which constructs the expensive object
  2. get the expensive object from the ThreadLocal in the method of interest

Simple - here's a code snippet, using the Java DateFormat class, with well-known thread-safety issues that are effectively moot here (since each thread will have its own copy):


private static final ThreadLocal<SimpleDateFormat> formatters =
new ThreadLocal() {
@Override
public SimpleDateFormat initialValue() {
return new SimpleDateFormat("yyyy-mm-dd_HH.mm.ss.SSS_");
}
};

......

SimpleDateFormat sdfFormatter = formatters.get();
String formattedDate = sdfFormatter.format(new Date());

Credit goes to Jeremy Manson in his post on this topic.

1 comment: