It will start nicely. Like most of the stories. You discover a new concept and are amazed by it’s powers. And then equipped with this new hammer suddenly everything starts to look like a nail. From what we have experienced in past months, java.lang.ThreadLocal makes one hell of a hammer.
I guess it all boils down to the very concept of how ThreadLocal works. It’s easiest to grasp the concept via the scoping analogy. In the very same way your Spring beans can be for example container, session or request scoped. ThreadLocal equips you with the possibility to declare objects in Thread scope.
You can set any object to ThreadLocal and this object will have both global and local scope in the thread accessing this object. It might be complex to grasp at first but let me explain:
So here we have a reason to celebrate – we have a truly powerful concept in our hands. It is often the easiest way to render a stateful class thread-safe. And encapsulate non-thread-safe classes so that they can safely be used in multithreaded environments. In addition to simplicity, using ThreadLocal to store a per-thread-singleton or per-thread context information has a valuable information included – by using a ThreadLocal, it’s clear that the object stored in the ThreadLocal is not shared between threads, simplifying the task of determining whether a class is thread-safe or not. Which we have found is not an easy task when you have a codebase of 1,000,000 lines at hand.
On the other hand, this powerful concept creates numerous problems in wrong hands. Like any other abused design concept. In the past months we have most often faced two problems:
If one of the application classes stores a value in ThreadLocal variable and doesn’t remove it after the task at hand is completed, a copy of that Object will remain with the Thread (from the application server thread pool). Since lifespan of the pooled Thread surpasses that of the application, it will prevent the object and thus a ClassLoader being responsible for loading the application from being garbage collected. And we have created a leak, which has a chance to surface in a good old java.lang.OutOfMemoryError: PermGen space form.
So should we avoid using ThreadLocal considering the harm it can cause? Maybe not so fast Joshua Bloch has said half a decade ago:
“Can you cause unintended object retention with thread locals? Sure you can. But you can do this with arrays too. That doesn’t mean that thread locals (or arrays) are bad things. Merely that you have to use them with some care. The use of thread pools demands extreme care. Sloppy use of thread pools in combination with sloppy use of thread locals can cause unintended object retention, as has been noted in many places. But placing the blame on thread locals is unwarranted.”
I tend to agree to Mr. Bloch and do not think ThreadLocal is an evil creation. But I also do think it is a concept which many fail to understand properly.
Inspiration for this article was mainly gathered during sleepless hours of tracing down some nasty bugs. But while writing, following resources proved to be beneficial as well:
If you enjoyed the post then – stay tuned for more. We continue to publish on interesting Java – related content on a weekly basis.