Thread-local variables in Java

In some cases, an alternative to synchronization is available in the form of thread-local variables. The technique has probably been a little overlooked in Java because in early JVMs, their implementation didn't take advantage of operating system support and actually didn't provide much performance advantage. But in later implementations (from around Java 1.4 onwards) they can provide a significant advantage in some cases.

So what is a thread-local variable? A thread-local variable is one whose value at any one time is linked to which thread it is being accessed from. In other words, it has a separate value per thread. Each thread maintains its own, separate map of thread-local variable values. (Many operating systems actually have native support for thread-local variables, but in Sun's implementation at least, native support is not used, and thread-local variables are instead held in a specialised type of hash table attached to the Thread.)

Thread-local variables are used via the ThreadLocal class in Java. We declare an instance of ThreadLocal, which has a get() and set() method. A call to these methods will read and set the calling thread's own value. So in this example, the two threads will effectively each have its own counter, incremented independently of the other thread:

final ThreadLocal perThreadCounter = new ThreadLocal();
Thread t1 = new Thread() {
  public void run() {
    perThreadCounter.set(new Integer(0));
    while (true) {
      Integer prevCount = (Integer) perThreadCounter.get();
      perThreadCounter.set(new Integer(prevCount.intValue() + 1));
    }
  }
}
Thread t2 = new Thread() {
  public void run() {
    perThreadCounter.set(new Integer(0));
    while (true) {
      Integer prevCount = (Integer) perThreadCounter.get();
      perThreadCounter.set(new Integer(prevCount.intValue() + 1));
    }
  }
}
t1.start();
t2.start();

Using ThreadLocal in Java 5

In Java 5 onwards, ThreadLocal has been adapted to support generics. This means you can write something like:

ThreadLocal<Calendar> calendarCache = new ThreadLocal<Calendar>();

Now on future accesses, we can do away with the cast:

Calendar cal = calendarCache.get();

On the next page, we look at a full example of using ThreadLocal.